「JavaSE」类和对象4:内部类

类和对象4

  • 内部类
    • 实例内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类
  • 总结

内部类

在 Java 中,我们可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现

注意:内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件

根据内部类定义的位置,可以分为两种形式:

  1. 成员内部类:实例内部类、静态内部类
  2. 局部内部类、匿名内部类

实例内部类

成员位置定义,并且没有被static修饰

  • 通过外部类引用来实例化实例内部类的对象
    必须先有外部类对象,然后才能创建实例内部类对象
public class Main {
    Out out = new Out();
    Out.InnerClass innerClass = out.new InnerClass();
}
  • 除非被final修饰成为常量,否则实例内部类不能有静态字段
    这很好理解,因为实例内部类的对象需要通过外部类对象产生,而静态字段不依赖对象而存在,所以这两者会产生冲突

而一个静态字段如果被final修饰,那就意味着它是一个常量,它在编译阶段就会被确定,因此它不依赖于外部类的实例
然后还需要注意,即使采用就地初始化也还是不行,因为静态字段是在类加载的时候初始化,在编译阶段仍然不能确定它的值

class InnerClass{
	public static int data2 = 20;  //编译报错
	public static final int data2 = 20;
}
  • 在实例内部类中可以访问外部类的任意成员
public class Out {
    public int data1 = 1;
    public static int data2 = 2;
    private int data3 = 3;
    
    class InnerClass{
    	public void Test() {
        	Out out = new Out();
        	System.out.println(out.data1);
        	System.out.println(data2);
        	System.out.println(out.data3);
    	}
    }
}
  • 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类的
    如果要访问外部类同名成员,需要按照“外部类名称.this.同名成员名字”的格式访问

    (这就类似父类和子类有同名的成员,如果不使用super进行访问,就会优先访问子类的)
public class Out {
    public int data1 = 1;
    public static int data2 = 2;
    private int data3 = 3;

    class InnerClass{
        public int data1 = 10;
        public static final int data2 = 20;
        public int data3 = 30;

        void method() {
            System.out.println(data1);
            System.out.println(data2);
        }
    }
}

    public static void main(String[] args) {
        Out out = new Out();
        Out.InnerClass innerClass = out.new InnerClass();
        innerClass.method();
    }

「JavaSE」类和对象4:内部类_第1张图片
实例内部类的非静态方法中包含了一个指向外部类对象的引用。所以实例内部类相当于有两个this:一个是内部类的this;另一个是访问外部类成员的Out.this

  • 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象
public class Out {
    public int data1 = 1;
     
    public void test() {
        InnerClass innerClass = new InnerClass();
        System.out.println(innerClass.data2);
    }

    class InnerClass{
        public int data2 = 10;
    }
}

静态内部类

顾名思义,就是用static修饰的内部类,它不依托外部类的对象存在,所以:

  1. 它不可以访问外部类的普通字段、方法(可以访问静态字段和静态方法)

「JavaSE」类和对象4:内部类_第2张图片
2. 创建静态内部类对象时,无需创建外部类对象

public static void main(String[] args) {
	// 静态内部类对象创建 & 成员访问
	Out.InnerClass innerClass = new Out.InnerClass();
	innerClass.methodInner();
}

局部内部类

定义在方法内部的类,只可以在方法内部使用(这种内部类很少用)

public class Out {
    public int data1 = 1;
    public static int data2 = 2;
    private int data3 = 3;
    
    public void func() {
    //类A只能在func里面使用
        class A {
            private int data4 = 4;
        }
        A aa = new A();
        System.out.println("data4" + aa.data4);
    }
}

匿名内部类

就是没有名字的内部类,通常可用于实现接口

public interface IA {
    void test();
}

public static void main(String[] args) {
    new IA(){
    	@Override
    	public void test() {
        	System.out.println("重写接口中的方法");
    	}
    };
}

从IA( )到大括号结束,就是匿名内部类,它实现了IA接口,然后前面使用new创建这个匿名内部类的对象
如果要调用它的test方法,有两种办法:

//第一种:直接在匿名内部类后面调用
new IA(){
	@Override
	public void test() {
        System.out.println("重写接口中的方法");
            }
    }.test();

//第二种:定义一个接口类型的引用指向这个对象,然后通过这个引用来调用方法
IA a = new IA(){
	@Override
    public void test() {
    	System.out.println("重写接口中的方法");
    }
};
a.test();

总结

  1. 根据定义的位置,内部类可以分为两种形式,一共有四种内部类
  2. 对于实例内部类,如果要访问外部类的成员,需要使用“外部类.this.外部类成员”访问
    外部类不能直接访问实例内部类中的成员,必须先创建内部类的对象
  3. 匿名内部类在开发过程经常使用,很重要

你可能感兴趣的:(快来卷Java啦,java,开发语言)