在Java语言中,类的访问修饰符决定了其它类能够访问该类的方式。类有如下4种访问修饰符,在创建类时用于类的声明:
1、public:
- 当一个类被声明为
public
时,它可以从任何其他类中被访问,无论这些类位于哪个包中。 - 通常,公共类包含公共的静态方法,这些方法可以被其他任何类调用,以及公共的实例方法,这些方法可以被其他任何类的实例调用。
- 顶层类只能是公开的或者是默认(包级私有)的。
2、protected:
protected
访问修饰符允许类被其所在包中的其他类以及所有子类访问,无论子类是在哪个包中。- 这意味着,如果一个类是在包
com.example
中声明的protected
,那么com.example
包中的任何其他类以及任何继承自这个类的子类(无论它们在哪个包中)都可以访问这个类。
3、默认访问修饰符(无修饰符):
- 当类没有显式声明任何访问修饰符时,它只能被其所在包中的其他类访问。
这种访问级别有时被称为“包级私有”,因为它限制了类只能在同一个包内部被访问。
4、private:
- 在Java中,
private
访问修饰符不能用于顶层类(即非内部类或非嵌套类)。 - 它只能用于类的成员(如字段、方法、内部类等),表示这些成员只能在它们自己的类中被访问。
下面是一个示例,展示了如何在Java中使用不同的访问修饰符来声明类:
// MyClass.java
public class MyClass { // public 类
// 可以在任何地方被访问
}
// AnotherClass.java
class AnotherClass { // 默认访问修饰符(无修饰符)的类
// 只能在同一个包中被访问
}
// ProtectedClass.java
protected class ProtectedClass { // protected 类
// 可以在同一个包中和所有子类中被访问
}
// InnerClass.java
public class OuterClass {
protected class ProtectedInnerClass { // 嵌套类可以是 protected
// 可以在同一个包中和所有子类中被访问
}
class DefaultInnerClass { // 默认访问修饰符的嵌套类
// 只能在同一个包中被访问
}
}
在Java中,private
访问修饰符修饰的类不能用于顶层类(即非内部类或非嵌套类)。顶层类总是具有包级私有访问权限:public,protectded,默认(没有任何修饰符,也具有包级私有访问权限)。
作为一个只能作为内部类的私有类,可以被在所在的顶层类中被实例化访问:
(1)在顶层类的方法中实例化访问;
(2)在顶层类中其它内部类中访问。
package com.test;
public class OuterClass {
/**
* 外部类(顶层类)OuterClass
* 类中嵌套3个类:分别为私有(private),静态(static),默认访问修饰符(无修饰符)的类
*/
private class PrivateInnerClass {
/**
* PrivateInnerClass是一个私有内部类,只能在顶层类OuterClass中被访问:
* 1、可以在OuterClass中方法中创建实例访问
* 2、也可以在OuterClass中的内部其他类中的方法中访问
* PrivateInnerClass类也可以访问顶层类OuterClass中的其它类。
*/
String name = "PrivateInnerClass.name";
public void test() {
// 创建内部类DefaultInnerClass的实例
DefaultInnerClass a = new DefaultInnerClass();
System.out.println("在私有内部类PrivateInnerClass类中调用DefaultInnerClass中属性name:" + a.name);
}
}
static class StaticNestedClass {
// 这是一个静态嵌套类,可以在任何地方被访问,因为它具有包级私有访问权限
String name = "StaticNestedClass.name";
}
class DefaultInnerClass {
// 这是一个默认访问修饰符的内部类,只能在同一个包中的OuterClass中被访问
String name = "DefaultInnerClass.name";
public void test() {
StaticNestedClass a = new StaticNestedClass();
System.out.println("在内部defalut类DefaultInnerClass中调用内部静态类StaticNestedClass的属性name:" +a.name);
PrivateInnerClass b = new PrivateInnerClass();
System.out.println("在内部defalut类DefaultInnerClass中调用内部私有类PrivateInnerClass的属性name:" +b.name);
}
}
// 定义print方法
public void print(String str) {
System.out.println(str);
PrivateInnerClass a = new PrivateInnerClass();
System.out.println("调用内部私有类PrivateInnerClass中的成员name" + a.name);
a.test();
StaticNestedClass b = new StaticNestedClass();
System.out.println("调用内部静态类StaticNestedClass中的成员name" + b.name);
DefaultInnerClass c = new DefaultInnerClass();
System.out.println("调用内部default类DefaultInnerClass中的成员name" + c.name);
c.test();
}
}
如上代码验证运行无误,另外需要理解的知识点:
对后缀为.java的文件进行编译,文件中的所有类都将被编译为一个独立的后缀为.class文件(java字节码文件)。
对于一个顶层类中定义了一个或者多个内部类也是如此,但是内部类编译后的.class类文件名是“顶层类名$私有类名.class"。编译如上代码OutClass.java文件,将产生如下几个文件:
1、顶层类文件:OutClass.class
2、私有类文件:OuterClass$DefaultInnerClass.class,OuterClass$PrivateInnerClass.class,OuterClass$StaticNestedClass.class。
这是Java提供的一个强大特性,即可以在单个文件中组织多个相关的类,同时保持它们在编译后的独立性。