目录
内部类,把一个类定义到另一个类的内部,就叫内部类
1. 成员内部类
可以把成员内部类当做 (class)类型的成员变量或者方法。
1 .内部类可以无条件访问外部类的所有成员方法和成员变量,静态变量,方法。构造方法不行。
2. 在1的前提下,如果当内部类拥有和外部类重名的方法或者变量时,会发生隐藏现象。在内部类直接使用时,只会使用内部类中的方法和变量,如果想要使用外部的方法或变量,需要 外部类.this.变量(方法)
例如:
System.out.println(Demo.this.name);
Demo.this.show();
3. 内部可以无条件访问外部类,但是外部是不能直接访问内部的。需要创建内部类对象去方法。
由于内部类是外部类的成员内部类,可以说该类是属于外部类的对象的。所以要想创建内部类,需要先创建外部类对象
例如:
Demo demo = new Demo();
Demo.DemoInner demoInner = demo.new DemoInner();
package com.mark.java.innerClass;
public class Demo {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("我是Demo");
}
class DemoInner{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void showInner(){
System.out.println("我是InnerDemo");
}
public void show(){
System.out.println("我是和外部类同名的方法show");
}
public void test(){
System.out.println(name);
System.out.println(this.name);
System.out.println(Demo.this.name);
Demo.this.show();
}
}
}
package com.mark.java.innerClass;
public class Main {
public static void main(String[] args) {
Demo demo = new Demo();
Demo.DemoInner demoInner = demo.new DemoInner();
demo.setName("zhangsan");
demoInner.showInner();
demoInner.setName("lisi");
demoInner.test();
}
}
2. 方法内部类
1. 一个类在另一个类的方法的内部。
2. 方法内部类,是局部内部类,只在该方法内部有意义,所以外部是无法创建该类的对象的,所以该类只能在方法内部使用。
package com.mark.java.innerClass;
public class Demo2 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(Demo2 demo2){
System.out.println("show");
//方法内部类,是局部内部类,只在该方法内部有意义,所以外部是无法创建该类的对象的,所以该类只能在方法内部使用。
class Demo2Inner{
private String name;
public void show(){
System.out.println(this.name);
System.out.println(Demo2.this.name);
System.out.println(demo2.getName());
}
}
Demo2Inner demo2Inner = new Demo2Inner();
demo2Inner.name = "bbbbb";
demo2Inner.show();
}
}
package com.mark.java.innerClass;
public class Main2 {
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
demo2.setName("aaaa");
demo2.show(demo2);
}
}
3. 匿名内部类
1. 不知道内部类的名称,叫匿名内部类。
2. 匿名内部类适合只使用一次的类,一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
3. 匿名内部类在编译后会默认生成一个Outter$1.class,匿名内部类时唯一没有构造方法的类。
4. 匿名内部类可以修改为成员内部类。帮助理解。
package com.mark.java.innerClass;
import org.springframework.aop.ThrowsAdvice;
public class Demo3{
public void aaa(){
//不知道内部类的名称,叫匿名内部类。
//2. 匿名内部类适合只使用一次的类,一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
//3. 匿名内部类在编译后会默认生成一个Outter$1.class,匿名内部类时唯一没有构造方法的类。
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类开始了");
}
}).start();
//同时可以写成成员变量的写法。这里起了名字一个类A。
new Thread(new A()).start();
}
class A implements Runnable{
@Override
public void run() {
System.out.println("不是匿名内部类的方式");
}
}
}
4. 静态内部类
1. 在内部类前面加一个static
2. 静态内部类不能访问外部类非静态的方法和属性,只能访问外部类静态的方法和属性
3. 外部类方法静态内部类,由于是静态类,所以该类是属于外部类的,而不是外部类对象的,所以创建静态内部类对象
Demo4.Demo4Inner demo4Inner = new Demo4.Demo4Inner();
package com.mark.java.innerClass;
public class Demo4 {
private String name;
private static int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("show");
}
public static void add(){
System.out.println("add");
}
static class Demo4Inner{
private String name;
private static int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("inner show");
//内部类方法外部类
System.out.println(Demo4.age);
//静态内部类不能访问外部类非静态的方法和属性。这个是错的
System.out.println(Demo4.this.name);
Demo4.add();
}
}
}
package com.mark.java.innerClass;
public class Main4 {
public static void main(String[] args) {
Demo4.Demo4Inner demo4Inner = new Demo4.Demo4Inner();
demo4Inner.show();
}
}
为什么内部类可以访问外部类呢
可以这样想,将内部类当做方法来想。
如果是成员内部类,就当成员方法,在成员方法中,可以访问该类的所有属性和方法。
如果是静态内部类,就当做静态方法,同理在静态方法中只能访问该类的静态变量和静态方法。
为什么局部内部类和匿名内部类只能访问局部final变量?
在之前,如下:,如果局部内部类和匿名内部类访问局部变量,局部变量必须是final修饰,现在不需要了
package com.mark.java.innerClass;
import org.springframework.aop.ThrowsAdvice;
public class Demo3{
public void aaa(final int a){
//不知道内部类的名称,叫匿名内部类。
//2. 匿名内部类适合只使用一次的类,一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
//3. 匿名内部类在编译后会默认生成一个Outter$1.class,匿名内部类时唯一没有构造方法的类。
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类开始了"+a);
}
}).start();
}
}
内部类的使用场景和好处
- 1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
- 2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
- 3.方便编写事件驱动程序。
- 4.方便编写线程代码。
参考:https://www.runoob.com/w3cnote/java-inner-class-intro.html