Java的public, protected, default, private 这个几个关键字的概念和差异理解 【一文搞懂】

Java的public, protected, default, private 这个几个关键字的概念和差异理解 【一文搞懂】

1.在Java中,public、protected、default(也称为包级私有)和 private 这四个关键字用来控制类、方法、变量等的访问权限。

以下是它们的通俗解释、概念和示例,最后还会给出一个对比表格,帮助你更直观地理解它们的异同。

1. public

概念:公开的,可以被任何地方的类访问。

通俗解释:如果一个方法、变量或类是 public 的,那么不论这个方法或变量所在的类在什么包中,都可以自由访问。

示例:

public class Person {

public String name;

public void sayHello() {

System.out.println("Hello, my name is " + name);

}

}

Person 类和 sayHello() 方法都被标记为 public,因此任何类都可以创建 Person 对象并调用 sayHello()。

2. protected

概念:受保护的,可以被同一个包中的类访问,或者被继承该类的子类访问(即使子类在不同的包中)。

通俗解释:protected 允许当前包内的所有类访问,另外允许其他包中的子类访问。

示例:

class Animal {

protected String type;

protected void makeSound() {

System.out.println("Animal is making a sound.");

}

}

class Dog extends Animal {

public void bark() {

makeSound(); // 可以访问父类的 protected 方法

System.out.println("Dog is barking.");

}

}

makeSound() 方法和 type 字段是 protected 的,因此可以在同一个包中的类或子类中被访问。

3. default(包级私有,未加修饰符)

概念:默认访问权限,也称包级私有,只有同一个包中的类可以访问,其他包中的类不能访问。

通俗解释:如果不加修饰符(例如没有写 public、protected、private),则为 default。只有在同一个包内的类可以访问,外部包无法访问。

示例:

class Car {

String model; // default 访问权限

void drive() { // default 访问权限

System.out.println("Driving the car.");

}

}

model 字段和 drive() 方法是 default 访问权限,它们只能在同一个包中的类访问,其他包中的类无法访问。

4. private

概念:私有的,只能在该类的内部访问。

通俗解释:private 使得该方法或变量只能在自己所在的类内部使用,其他类甚至在同一个包中也无法访问。

示例:

class BankAccount {

private double balance; // private 变量

private void updateBalance() { // private 方法

System.out.println("Updating balance...");

}

public void deposit(double amount) {

balance += amount;

updateBalance(); // 类内部可以访问 private 方法

}

}

balance 和 updateBalance() 是 private,因此只能在 BankAccount 类内部使用,其他类无法访问这些成员。

访问控制修饰符对比表

访问修饰符同一个类内部同一个包内不同包的子类不同包的非子类

public

protected

default

private

总结:

public:最宽松的访问权限,任何地方都可以访问。

protected:允许同包内访问,此外允许子类(无论在哪个包)访问。

default(未加修饰符):仅限于包内访问,其他包无法访问。

private:最严格的访问权限,只能在类内部访问。

通过这些概念和示例,就可以清楚地看到每个访问控制修饰符的使用场景和具体区别。

2.下面举例加强理解:

访问修饰符同一个类内部同一个包内不同包的子类不同包的非子类

public

protected

default

private

为了清晰说明 public、protected、default、private 修饰符在 同一个类内部、同一个包内、不同包的子类、不同包的非子类 的16种情况,以下我将通过一个完整的例子进行讲解。

示例结构:

我们定义两个包:com.example 和 com.other

在 com.example 包中,我们有一个父类 Parent 和一个子类 Child。

在 com.other 包中,我们定义一个类 OtherChild,它继承自 Parent,并且我们还有一个类 NonChild,它不继承自 Parent。

Parent 类包含 public、protected、default 和 private 修饰的成员,展示它们在不同场景下的访问情况。

代码结构:

com.example.Parent.java(父类,包含所有修饰符示例)

com.example.Child.java(同包中的子类)

com.other.OtherChild.java(不同包中的子类)

com.other.NonChild.java(不同包中的非子类)

我会添加 main() 函数作为入口,方便你更直观地运行和测试访问权限的差异。

下面我将为每个类添加 main() 方法,用来展示不同场景下如何访问不同修饰符定义的字段。【每个类都能够添加main()函数?见后面追问】

1. com.example.Parent.java(父类,包含main()入口):

package com.example;

public class Parent {

public String publicField = "Public Field";

protected String protectedField = "Protected Field";

String defaultField = "Default Field"; // default 访问权限

private String privateField = "Private Field";

public void accessFields() {

// 同一个类内部,所有字段都能访问

System.out.println("Inside Parent class:");

System.out.println("Public Field: " + publicField); // ✅

System.out.println("Protected Field: " + protectedField); // ✅

System.out.println("Default Field: " + defaultField); // ✅

System.out.println("Private Field: " + privateField); // ✅

}

public static void main(String[] args) {

Parent parent = new Parent();

parent.accessFields(); // 测试同一个类内部访问

}

}

2. com.example.Child.java(同包的子类,包含main()入口):

package com.example;

public class Child extends Parent {

public void testAccess() {

System.out.println("Inside Child class (same package):");

// 同一个包的子类可以访问 public、protected 和 default 字段,但不能访问 private 字段

System.out.println("Public Field: " + publicField); // ✅

System.out.println("Protected Field: " + protectedField); // ✅

System.out.println("Default Field: " + defaultField); // ✅

// System.out.println(privateField); // ❌ 编译错误

}

public static void main(String[] args) {

Child child = new Child();

child.testAccess(); // 测试同包的子类访问

}

}

3. com.other.OtherChild.java(不同包中的子类,包含main()入口):

package com.other;

import com.example.Parent;

public class OtherChild extends Parent {

public void testAccess() {

System.out.println("Inside OtherChild class (different package):");

// 不同包中的子类可以访问 public 和 protected 字段,不能访问 default 和 private 字段

System.out.println("Public Field: " + publicField); // ✅

System.out.println("Protected Field: " + protectedField); // ✅

// System.out.println(defaultField); // ❌ 编译错误

// System.out.println(privateField); // ❌ 编译错误

}

public static void main(String[] args) {

OtherChild otherChild = new OtherChild();

otherChild.testAccess(); // 测试不同包的子类访问

}

}

4. com.other.NonChild.java(不同包的非子类,包含main()入口):

package com.other;

import com.example.Parent;

public class NonChild {

public void testAccess() {

Parent parent = new Parent();

System.out.println("Inside NonChild class (different package, non-subclass):");

// 不同包中的非子类只能访问 public 字段,不能访问 protected、default 和 private 字段

System.out.println("Public Field: " + parent.publicField); // ✅

// System.out.println(parent.protectedField); // ❌ 编译错误

// System.out.println(parent.defaultField); // ❌ 编译错误

// System.out.println(parent.privateField); // ❌ 编译错误

}

public static void main(String[] args) {

NonChild nonChild = new NonChild();

nonChild.testAccess(); // 测试不同包的非子类访问

}

}

各类执行顺序:

Parent 类的 main() 将展示同类内的所有字段访问,验证 public、protected、default 和 private 都可以访问。

Child 类的 main() 将展示同包子类中的字段访问,验证 public、protected、default 字段可以访问,private 无法访问。

OtherChild 类的 main() 将展示不同包的子类访问,验证 public 和 protected 可以访问,default 和 private 无法访问。

NonChild 类的 main() 将展示不同包的非子类访问,验证只有 public 字段可以访问,其他字段无法访问。

总结:

通过这些简单的 main() 方法,可以直接运行代码并查看输出,帮助你理解各个访问修饰符在不同场景中的权限控制效果。这也让你可以直观地看到每个类在不同情况下的访问权限差异。

3.追问:main()函数应该只能存在于一个.java文件中吧?

不,main() 函数可以存在于多个 .java 文件中。每个 Java 类都可以有一个 main() 方法,只要它们是独立的类。

每个类的 main() 方法都是程序的入口点,但只有一个 main() 方法会被 Java 虚拟机(JVM)调用,具体取决于你运行的类。

示例

假设有三个文件:

Parent.java

package com.example;

public class Parent {

public static void main(String[] args) {

System.out.println("This is the Parent class.");

}

}

2.Child.java

package com.example;

public class Child {

public static void main(String[] args) {

System.out.println("This is the Child class.");

}

}

3.OtherChild.java

package com.other;

public class OtherChild {

public static void main(String[] args) {

System.out.println("This is the OtherChild class.");

}

}

运行示例

当你运行时,如果你在命令行中执行 java com.example.Parent,输出将是:

This is the Parent class.

如果你执行 java com.example.Child,输出将是:

This is the Child class.

而如果你执行 java com.other.OtherChild,输出将是:

This is the OtherChild class.

总结

多个 main() 方法:在不同的类中可以有多个 main() 方法,每个方法都是独立的入口点。

选择运行:你可以选择运行任何一个类的 main() 方法,而 JVM 只会执行你指定的那个类的 main() 方法。

这允许你在一个项目中有多个类的测试或独立执行,便于开发和调试。

相关推荐

联想平板电脑能用多久

联想平板电脑能用多久

📅 07-10 👁️ 9713
先锋攻略:90级神力极速升级

先锋攻略:90级神力极速升级

📅 08-05 👁️ 9148
适合室内玩的小游戏有哪些

适合室内玩的小游戏有哪些

📅 08-13 👁️ 3415