JAVA内部类是怎么玩儿的

内部类一共分为:成员内部类,局部内部类,静态嵌套类,匿名内部类。java

1. 成员内部类

最普通的内部类多线程

class Outter {
    private int age = 12;
      
    class Inner {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部变量:" + age);
            System.out.println("内部类变量:" + this.age);
            System.out.println("外部类变量:" + Outter.this.age);
        }
    }
}
  
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        Outter.Inner in = out.new Inner();
        in.print();
    }
}

成员内部类,就是做为外部类的成员,能够直接使用外部类的全部成员和方法,即便是private的。虽然成员内部类能够无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么为所欲为了。在外部类中若是要访问成员内部类的成员,必须先建立一个成员内部类的对象,再经过指向这个对象的引用来访问this

要注意的是,成员内部类不能含有static的变量和方法。由于成员内部类须要先建立了外部类,才能建立它本身的。可是将其加一个final,就能够了,因此还须要追究一下final static和static的区别spa

2. 局部内部类

局部内部类是定义在一个方法或者一个做用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该做用域内。线程

定义在方法中

class Outter {
 
    private int age = 12;
      
    public void Print(final int x) {    //这里局部变量x必须设置为final类型!
        class Inner {
            public void inPrint() {
                System.out.println(x);
                System.out.println(age);
            }
        }
        new Inner().inPrint();
    }
      
 
}
  
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        out.Print(10);
    }
}

本例中咱们将内部类移到了外部类的方法中,而后在外部类的方法中再生成一个内部类对象去调用内部类方法。若是此时咱们须要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义。code

换句话说,在方法中定义的内部类只能访问方法中final类型的局部变量,这是由于在方法中定义的局部变量至关于一个常量,它的生命周期超出方法运行的生命周期,因为局部变量被设置为final,因此不能再内部类中改变局部变量的值。(解释的一坨屎,还须要再深究)对象

定义在做用域中

class Outter {
  private int age = 12;
  public void Print(final boolean x) {  //这里局部变量x必须设置为final类型!
        if(x){
             class Inner {
                    public void inPrint() {
                        System.out.println(x);
                    }
                }
             new Inner().inPrint();
        }      
    }
}
  
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        out.Print(true);
    }
}

3. 静态嵌套类

又叫静态局部类、嵌套内部类,就是修饰为static的内部类。声明为static的内部类,不须要内部类对象和外部类对象之间的联系,就是说咱们能够直接引用outer.inner,即不须要建立外部类,也不须要建立内部类。继承

class Outter {
    private static int age = 12;
    static class Inner {
        public void print() {
            System.out.println(age);
        }
    }
}
  
public class test1 {
    public static void main(String[] args) {
        Outter.Inner in = new Outter.Inner();
        in.print();
    }
}

能够看到,若是用static 将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具备局限性接口

其次,由于内部类被静态化,所以Outter.Inner能够当作一个总体看,能够直接new 出内部类的对象(经过类名访问static,生不生成外部类对象都不要紧生命周期

4. 匿名内部类

匿名内部类也就是没有名字的内部类

正由于没有名字,因此匿名内部类只能使用一次,它一般用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

咱们先来看一个例子,不使用匿名内部类实现方法

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

假设Child类只用一次,那么这样作成一个类就是太浪费了。因此这个时候咱们用匿名内部类实现就比较好:

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

在接口上实现内部类:

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

由上面的例子能够看出,只要一个类是抽象的或是一个接口,那么其子类中的方法均可以使用匿名内部类来实现

最经常使用的状况就是在多线程的实现上,由于要实现多线程必须继承Thread类或是继承Runnable接口

相关文章
相关标签/搜索