类的五大成员:属性, 方法, 构造器, 代码块, 内部类
内部类的分类:
1.定义在外部类局部位置上((方法中,代码块中)): ① 局部内部类(有类名) ② 匿名内部类(无类名)
2.定义在外部类的成员位置上 :①成员内部类(没用static修饰) ②静态内部类(用static修饰)
局部内部类
说明:局部内部类 是定义在外部类内的局部位置,(方法中,代码块中),有类名
1. 可以直接访问外部类的所有成员,包含私有的。
2. 不能添加访问修饰符,因为他的地位就是一个局部变量,局部变量是不能使用修饰符的,但是可以用final修饰,因为局部变量也可以final修饰
3. 作用域 :仅在 定义它的方法或者代码块中
4. 局部内部类 --- 访问 --- 》外部类的成员【访问方式:直接访问】
5.外部类要 访问 局部内部类的成员 【访问方式:创建内部类对象再访问】
6.外部其他类不能访问局部内部类【因为局部内部类本质上属于一个局部变量】
7.如果外部类和局部内部类的成员重名,默认就近原则,如果想要访问外部类的成员可以使用(外部类名.this.成员)去访问
8. 局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
匿名内部类
本质: 类 内部类 该类没有名字 同时还是一个对象
基于接口的匿名内部类
基于类的匿名内部类
public class AnonymousInnerClass { public static void main(String[] args) { Outer04 outer04 = new Outer04(); outer04.method(); } } class Outer04 { //外部类 private int n1 = 10;//属性 public void method() { //基于接口的匿名内部类 // 3.老韩需求是 Tiger/Dog 类只是使用一次,后面再不使用 // 4. 可以使用匿名内部类来简化开发 // 5. tiger 的编译类型 ? IA // 6. tiger 的运行类型 ? 就是匿名内部类 Outer04$1 /* 我们看底层 会分配 类名 Outer04$1 class Outer04$1 implements IA { @Override public void cry() { System.out.println("老虎叫唤..."); } } */ //7. jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例, // 并且把地址 // 返回给 tiger //8. 匿名内部类使用一次,就不能再使用 IA tiger = new IA() { @Override public void cry() { System.out.println("老虎叫唤..."); } }; System.out.println("tiger 的运行类型=" + tiger.getClass()); //基于类的匿名内部类 //1. father 编译类型 Father //2. father 运行类型 Outer04$2 //3. 底层会创建匿名内部类 /* class Outer04$2 extends Father{ @Override public void test() { System.out.println("匿名内部类重写了 test 方法"); } } */ //4. 同时也直接返回了 匿名内部类 Outer04$2 的对象 // 5. 注意("jack") 参数列表会传递给 构造器 Father father = new Father("jack") { @Override public void test() { System.out.println("匿名内部类重写了 test 方法"); } }; System.out.println("father 对象的运行类型=" + father.getClass());//Outer04$2 father.test(); } } interface IA{ public void cry(); } class Father{ private String name; public Father(String name) { this.name = name; } public void test(){ System.out.println("KK"); } }细节:
匿名内部类在底层实现中,要么是返回实现了接口的类的实例,要么返回继承了某类的子类实例
1.匿名内部类可以直接调用外部类的全部成员,包括私有
2. 不能添加访问修饰符,因为本质是个局部变量
3.作用域仅在定义它的方法或代码块中
4.外部其他类不能访问匿名内部类,理由同局部内部类
5..如果外部类和局部内部类的成员重名,默认就近原则,如果想要访问外部类的成员可以使用(外部类名.this.成员)去访问
最佳实践:
① 当作实参直接传递
public class InnerClass { public static void main(String[] args) { f1(new IL(){ @Override public void show() { System.out.println("hah"); } }); } //形参是接口类型 public static void f1(IL il){ il.show(); } } interface IL{ public void show(); }
成员内部类
直接定义在外部类的成员位置,而不是再方法或者代码块中,并且没有static修饰
public class InnerClass { public static void main(String[] args) { AA aa = new AA(); aa.kk(); } } class AA{ private int n1 = 10; public String name = "zaz"; class BB{//可以直接调用外部类的全部成员包括私有 public void say(){ System.out.println("haha"); } } public void kk(){ BB bb = new BB(); bb.say(); } }因为其地位是一个类的成员,因此可以用(public privated protected 默认)的访问修饰符修饰,
细节:
可以直接访问外部类全部成员, 外部类要先创建对象才能访问
外部其他类可以访问成员内部类,有二种方式:
public class InnerClass { public static void main(String[] args) { AA aa = new AA(); //普通成员是实例层面, 因此要确定是哪个对象创建内部类对象,因此是XX外部类对象名.new 成员内部类名() AA.BB bb = aa.new BB(); } }在外部类中定义一个方法用于返回内部类对象
public class InnerClass { public static void main(String[] args) { AA aa = new AA(); AA.BB bb = aa.getBB(); bb.say(); } } class AA{ private int n1 = 10; public String name = "zaz"; class BB{ public void say(){ System.out.println("haha"); } } public BB getBB(){ return new BB(); } }静态内部类
与成员内部类相比他的定义前需要用static修饰,因此它属于类,是个类变量,而不是普通的成员变量,只能访问外部类全部的静态成员
外部类访问要先创建对象,在访问
class AA{ private int n1 = 10; public String name = "zaz"; static class BB{ public void say(){ System.out.println("haha"); } } public void kk(){ BB bb = new BB(); bb.say(); } }外部其他类访问静态内部类:
public class InnerClass { public static void main(String[] args) { AA.BB bb = new AA.BB();//但是该静态内部类仍然要满足访问权限,使用private 修饰不可以创建 bb.say(); } } //第二种方法就是定义一个返回静态内部类对象的方法