【Java】内部类

做题目时经常遇到,始终没能完全搞清楚,这里总结一下

内部分类:

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

成员内部类

  1. 相当于外部类的一个成员变量,可以用任意访问修饰符
  2. 定义的方法可以直接访问外部类的数据,不受访问控制符的影响,比如private
  3. 成员内部类的成员不能声明为static的
  4. 在外部类的静态成员使用内部类时,内部类要该为静态内部类
  5. 编译上述语句后产生两个.class文件:Outer.class,Outer$Inner.class{}
  6. 在内部类里默认访问自己的成员变量或方法,要访问外部类的,用外部类对象.this.name
public class Outer{
    private int age = 18;
    String name = "wang";
    public class Inner{
        String name = "wan";
        //static String name = "wan";//不能使用static修饰成员变量和方法
        public void method(){
            System.out.println(Outer.this.name);//使用外部类成员:外部类名.this.成员
            System.out.println(name);//默认使用内部类的成员
            System.out.println(age);//内部类没有的话就用外部类的
        }
    }
    public Inner getInnerClass(){
        return new Inner();//外部类要先创建内部类对象才能访问内部类
    }
    public static void main(String[] args){
        Outer outer = new Outer();
        Inner in = outer.new Inner();//内部类 对象名 = 外部类对象.new 内部类()
        in.method();
    }
}

静态内部类

  • 只能访问外部静态成员
  • 属于外部类本身,不属于外部类某个对象

静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法。

class Outter {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner();
    }
    static class Inner {
        public Inner() {}
    }
}

静态内部类实现延迟加载单例模式

静态内部类和成员内部类一样,都不会因为外部类的加载而加载,在使用时才加载。在加载静态内部类时也会加载外部类。

public class SingletonIniti {
    private SingletonIniti() {}
    private static class SingletonHolder {
        private static final SingletonIniti INSTANCE = neSingletonIniti();
    }
    public static SingletonIniti getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

局部内部类

  • 其作用域仅限于方法内,方法外部无法访问该内部类

  • 不能有public、protected、private 以及 static 修饰符

  • 只能访问方法中的final的局部变量,因为方法调用完了后就没了,而局部内部类还可以存在

    在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的, 也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用 final 来避免形参的不改变

    注意:在JDK8版本之中,方法内部类中调用方法中的局部变量,可以不需要修饰为 final,匿名内部类也是一样的,主要是JDK8之后增加了 Effectively final 功能

    反编译jdk8编译之后的class文件,发现内部类引用外部的局部变量都是 final 修饰的

    public class Outer{
        public void Show(){
            final int a = 25;
            int b = 13;
            class Inner{
                int c = 2;
                public void print(){
                    System.out.println("访问外部类:" + a);
                    System.out.println("访问内部类:" + c);
                }
            }
            Inner i = new Inner();
            i.print();
        }
        public static void main(String[] args){
            Outer o = new Outer();
            o.show();
        }
    }  
    

匿名内部类

new 类/接口{
    //写了一堆东西;
};
  • 只能访问局部final变量(JDK8开始可以不用final,系统默认加了)
  • 不能有构造方法
  • 不能定义任何静态的成员、方法
  • 只能创建一个实例
  • 必须且只能继承一个类或者实现一个接口
public class OuterClass {
    public InnerClass getInnerClass(final int   num,String str2){
        return new InnerClass(){
            int number = num + 3;
            public int getNumber(){
                return number;
            }
        }; //注意:分号不能省 
    }
    public static void main(String[] args) {
        OuterClass out = new OuterClass();
        InnerClass inner = out.getInnerClass(2, "chenssy");
        System.out.println(inner.getNumber());
    }
}
interface InnerClass {
    int getNumber();
}         
posted @ 2020-10-13 21:19  菜鸡土豆  阅读(155)  评论(0)    收藏  举报