文章目录
内部类
允许一个类定义在另一个类的内部,前者称为内部类,后者称为外部内
1.内部类可以使用外部类的私有数据(因为是外部类的成员,同一个类的成员之间可以互相访问)
2.外部类想要访问内部类中的成员时,需要内部类.成员
或 内部类对象.成员
1.非静态内部类
没有使用static修饰的成员内部类是非静态内部类
1.不是说一个源程序中只能有一个public类?怎么内部类可以用public?
“在同一个源程序中只能有一个public类”应该理解为只有一个public类的名字与源码文件名一致。
特点:
1.当在非静态内部类的方法
内访问某个变量时候,系统会优先查找该方法
内是否存在该名字的局部变量,若存在,则使用,若不存在,那么再在方法所在的内部类
中查找,找到则使用,若没找到,则再在该内部类所在的外部类
中继续查找,找到则用,否则报找不到错误。
2.外部类属性/内部类属性与内部类里的方法的局部变量同名,那么可以用this或外部类名.this来限定区分
3.非静态内部类可以访问外部类的Private成员,反之不成立。非静态内部类的成员,只能在非静态(实例)内部类里使用,并不能被外部类直接使用。若外部类需要访问非静态内部类,则必须显示创建非静态内部类对象
来访问其实例成员。
4.根据静态成员不能访问非静态成员的规则,外部类的静态方法,静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义的变量,创建实例等,总之不允许在外部类的静态成员中直接使用非静态内部类
5.不允许在非静态内部类里定义静态成员(方法,变量等),即非静态内部类里不能有静态方法、属性、初始化块
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.outPrint();
}
public class OutClass {
private String o1 = "外部类的实例变量";
private static String o2 = "外部类的静态变量";
//private:表示本内部类只能在外部类里面使用,其他外面都不能调用此内部类
private class inClass{
private String o1 = "内部类的实例变量o1";
private String i1 = "内部类的实例变量i1";
//**************特点:4,5
// //报错:非静态内部类,不能申明静态属性
// private static String o2 = "外部类的静态变量";
public void print(){
//**********特点1,2
String o1 = "内部类局部变量o1";
// 通过 外部类类名.this.varName 访问外部类实例变量
System.out.println("外部类的实例变量值:"+ OutClass.this.o1);
// 通过 this.varName 访问内部类实例的变量
System.out.println("内部类的实例变量值:" + this.o1);
// 直接访问局部变量
System.out.println("局部变量的值:" + o1);
}
}
public void outPrint(){
System.out.println("外部类的实例变量值:"+ o1);
//报错:未定义这个变量
// System.out.println("外部类的实例变量值:"+ i1);
//*********特点3:非实例内部类必须先实例化才能使用
inClass inClass = new inClass();
System.out.println("内部类:" + inClass.o1);
inClass.print();
}
}
2.静态内部类
使用static修饰的成员内部类是非静态内部类
特点:
1.根据静态成员不能访问非静态成员的规则,外部类的静态方法,静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义的变量,创建实例等,总之不允许在外部类的静态成员中直接使用非静态内部类
2.静态内部类可以包含有静态方法、属性、初始化块,但静态内部类不能访问外部类的实例成员
,即使静态内部类的实例方法
也不能访问外部类的实例成员
public class OutClass1 {
private String o1 = "外部类成员变量o1";
private static String o2 = "外部类静态变量o2";
static class inClass{
void print(){
//报错:o1变量找不到
System.out.println("inClass-o1:"+o1);
//o2可以使用
System.out.println("inClass-o1:"+o2);
}
}
}
3.外部类依然不能直接
访问静态内部类成员,但可以使用静态内部类的类名
作为调用者来访问静态内部类的类成员,也可使用静态内部类的对象
作为调用者来访问静态内部类的实例成员。
public class OutClass2 {
private static String o2 = "外部类静态变量o2";
static class InClass{
private static String o2 = "内部类静态变量o2";
}
void print(){
System.out.println(o2);
//内部类类.成员
System.out.println(InClass.o2);
//内部类对象.成员
System.out.println(new InClass().o2);
}
public static void main(String[] args) {
OutClass2 outClass2 = new OutClass2();
outClass2.print();
}
}
3.局部内部类
若把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。局部内部类不能在外部类以外的地方使用,那么局部内部类也无需使用访问控制符合static修饰
特点:
1.对于局部内部类,它们的上一级程序单元是方法
,而不是类
。
public class OutClass7 {
private String name = "外部类";
void show(final String str){
class InClass{
private String name = "内部类";
void print(){
System.out.println("name = " + name + str);
}
}
//整个生命周期在方法里
InClass inClass = new InClass();
inClass.print();
}
public static void main(String[] args) {
OutClass7 outClass7 = new OutClass7();
outClass7.show("demo");
}
}
3.1 匿名内部类
匿名内部类适合创建只需要一次使用的类,匿名内部类不能重复使用。没有类名的局部内部类
特点:
1.匿名内部类必须继承一个父类,或实现一个借接口,但最多只能继承一个父类或者实现一个接口,并且需要实现所有抽象方法
2.匿名内部类不能是抽象类。因为系统创建匿名内部类的时候,会立即创建匿名内部类对象,而抽象类不能直接创建。
3.匿名内部类不能定义构造器。因为匿名内部类米有类名,所以无法定义构造器
//定义一个接口
interface Parent{
public String getName();
}
public class OutClass5 {
public void MyName(Parent parent){
System.out.println("我的名字"+parent.getName());
}
public static void main(String[] args) {
//匿名内部类,实现一个接口
new OutClass5().MyName(new Parent() {
@Override
public String getName() {
return "parent";
}
});
}
}
4.若匿名内部类需要访问外部类的局部变量,则需要使用final修饰外部类的局部变量,否则会报错
5.匿名内部类中不能存在任何的静态成员变量和静态方法
4.使用内部类
4.1 在外部类内部使用内部类
1.在外部类里使用内部类,和平常使用普通类方式一样
2.不要在外部类的静态成员(比如静态方法或静态代码块
)中使用非静态内部类(静态成员不能访问非静态成员)
public class OutClass6 {
static class InClass{
private String name = "内部类";
void print(){
System.out.println("name = " + name);
}
}
public static void main(String[] args) {
//在外部类里使用,无需通过外部类.内部类这种,直接就可以像普通类的操作那样直接用就行了
InClass inClass = new InClass();
inClass.print();
}
}
4.2 在外部类以外使用非静态内部类
1.若希望外部类以外
的地方访问内部类,则内部类不能使用private修饰
- 省略修饰控制符的内部类,只能被与外部类同属于一个包的其他类所访问
- 使用protected修饰的内部类,只能被同一个包或者子类所访问
- 使用public修饰的内部类,可以被任何地方的其他类访问
2.因为非静态内部类的对象必须寄存于外部类的对象中,所以创建非静态内部类对象时,必须先创建其外部类的对象,即非静态内部类的构造器必须通过其外部类对象来调用
public class OutClass3 {
private static String o2 = "外部类静态变量o2";
class InClass{
private String o2 = "内部类静态变量o2";
}
public static void main(String[] args) {
OutClass3.InClass in = new OutClass3().new InClass();
//o2之所以能访问,是因为private在同一个内里是可以互相访问的,但若是在其他类中,则不能访问
System.out.println(in.o2);
/*
上面代码可改为如下三行代码:
使用OutterClass.InnerClass的形式定义内部类变量
Out.In in;
创建外部类实例,非静态内部类实例将寄存在该实例中
Out out = new Out();
通过外部类实例和new来调用内部类构造器创建非静态内部类实例
in = out.new In("测试信息");
*/
}
}
4.3 在外部类以外使用静态内部类
1.因为静态内部类是外部类类相关的,因此创建内部类对象时无需创建外部类的对象
public class OutClass4 {
private static String o2 = "外部类静态变量o2";
static class InClass{
// 定义一个静态内部类,不使用访问控制符,
// 即同一个包中其他类可访问该内部类
public InClass()
{
System.out.println("静态内部类的构造器");
}
}
public static void main(String[] args) {
OutClass4.InClass in = new OutClass4.InClass();
/*
上面代码可改为如下两行代码:
使用OutterClass.InnerClass的形式定义内部类变量
StaticOut.StaticIn in;
通过new来调用内部类构造器创建静态内部类实例
in = new StaticOut.StaticIn();
*/
}
}
静态类
参考:
java内部类作用
java内部类深入详解 内部类的分类 特点 定义方式 使用
java 内部类的好处和缺点(下)
java内部类作用
详解 Java 内部类