Java四种内部类
内部类
-
一个类的内部里面又完整的嵌套了另一个类的内部结构,被嵌套的类称为内部类
-
内部类最大的特点就是:可以直接访问私有属性,并且可以体现类与类之间的包含关系
-
基本语法
class outer{ //外部类 private int n1 = 100; public outer(int n1) { this.n1 = n1; } public void m1(){ System.out.println("m1方法"); } { System.out.println("代码块"); } //内部类 class Inner{ } }
- 局部内部类
特点:
-
1.局内内部类是定义在外部类的局部位置,通常是定义在方法中,也可以定义在代码块内
-
2.局部内部类可以直接访问外部类的所有成员,包括私有的
-
3.局部内部类不可以有访问修饰符,但是可以使用final进行修饰
-
4.作用域:仅仅在他定义的方法或者代码块中
-
5.外部类在方法中,可以创建Inner02对象,然后直接调用方法即可
-
6.外部其他类不能访问局部内部类,因为局部内部类是成员变量
-
7.如果外部类和局部内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 this.外部成员进行访问
public class LocalInnerClass { public static void main(String[] args) { //6.外部其他类不能访问局部内部类,因为局部内部类是成员变量 outer2 outer2 = new outer2(); outer2.m1(); } } class outer2{ //外部类 private int n1 = 100; private void m2(){ System.out.println("m2方法"); } public void m1(){ //1.局内内部类是定义在外部类的局部位置,通常是定义在方法中,也可以定义在代码块内 //3.局部内部类不可以有访问修饰符,但是可以使用final进行修饰 //4.作用域:仅仅在他定义的方法或者代码块中 //final class Inner02{ class Inner02{//局部内部类 本质仍然是一个类 private int n1 = 80; //2.局部内部类可以直接访问外部类的所有成员,包括私有的 public void f1(){ System.out.println(n1); System.out.println(outer2.this.n1); System.out.println(this.n1); m2(); //7.如果外部类和局部内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 外部类名.this.外部成员进行访问 } } //5.外部类在方法中,可以创建Inner02对象,然后直接调用方法即可 Inner02 inner02 = new Inner02(); inner02.f1(); class Inner03 extends Inner02{ } } //代码块中定义内部类 //{ // class Inner02{ // //2.局部内部类可以直接访问外部类的所有成员,包括私有的 // public void f1(){ // System.out.println(n1); // } // } //} }
2.匿名内部类
-
匿名内部类也是一个类的定义,同时它本身也是一个对象,因此从语法上看。它既有定义类的特征,也有创建 对象对的特征
-
可以直接访问外部类的所有成员,包含私有的
-
不能添加访问修饰符,它的本质其实是一个局部变量
-
不能添加访问修饰符,它的本质其实是一个局部变量
-
作用域:仅仅在它定义的代码块中 外部其他类不能访问匿名内部类,因为匿名内部类是成员变量 如果外部类和匿名内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 this.外部成员进行访问
public class AnonymousClass { public static void main(String[] args) { outer03 outer03 = new outer03(); outer03.m1(); } } class outer03{ private int n1 = 100; public void m1(){ //基于接口的匿名内部类 //使用IAn接口创建对象 在开发中我们只使用一次这个对象 所以创建对象有点浪费 //Tiger tiger = new Tiger(); //tiger.cry(); //解决方法:使用匿名内部类创建对象 // tiger 的编译类型 ? IA // tiger 的运行类型 ? 就是匿名内部类 Outer04$1 // jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址返回给tiger // 匿名内部类只能使用一次,就不能在使用 IAn tiger = new IAn(){ @Override public void cry() { System.out.println("tiger的cry方法"); } }; tiger.cry(); System.out.println("tiger的运行类型"+ tiger.getClass()); //基于类的匿名内部类 Father father = new Father(){ @Override public void test() { System.out.println("重写了father的test方法"); } }; father.test(); //基于抽象类的匿名内部类 Animal animal = new Animal(){ @Override void test() { System.out.println("重写了animal的test方法"); } }; animal.test(); } } //接口 interface IAn{ //cry方法 void cry(); } //class Tiger implements IAn{ // // @Override // public void cry() { // // } //} class Father{ private int n1 = 100; public void test(){ } } abstract class Animal{ private int n1 = 100; abstract void test(); }3.成员内部类
特点:
-
可以直接访问外部类得成员,包括私有得
-
成员内部类可以添加访问你修饰符(private,default,protected,public)
-
作用域:在外部类得类体中
如果外部类和成员内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 this.外部成员进行访问
public class MemberInnerClass { public static void main(String[] args) { Outer outer = new Outer(); outer.test(); //外部类访问成员内部类 Outer.Inner03 inner03 = outer.new Inner03(); inner03.say(); } } class Outer{ private int n = 100; //成员内部类可以访问所有的成员 包括私有的 //成员内部类可以添加访问你修饰符(private,default,protected,public) //作用域:在外部类得类体中 class Inner03{ public void say(){ System.out.println(n); System.out.println("成员内部类方法"); } } public void test(){ Inner03 inner03 = new Inner03(); inner03.say(); } }
4.静态内部类
特点:
- 可以直接访问外部类得非静态成员,包括私有的
- 可以添加任意的修饰符(private等等)
- 作用域:同其他成员,为整个类体
-
如果外部类和静态内部类成员重名时,默认遵守就进原则,如果想访问外部类的成员可以使用 外部类名.成员进行访问
public class StaticInnerClass { public static void main(String[] args) { Outer10.Inner10 inner10 = new Outer10.Inner10(); inner10.say(); } } class Outer10 { private int n1 = 10; private static String name = "张三"; private static void cry() { } //Inner10 就是静态内部类 // 1. 放在外部类的成员位置 // 2. 使用 static 修饰 // 3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员 // 4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员 // 5. 作用域 :同其他的成员,为整个类体 static class Inner10 { private static String name = "1111"; public void say() { //如果外部类和静态内部类的成员重名时,静态内部类访问的时, // 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员) System.out.println(name + " 外部类 name= " + Outer10.name); cry(); } } }