java——内部类

Posted 高圈圈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java——内部类相关的知识,希望对你有一定的参考价值。

用来实现“多重继承”

内部类:实现代码被置于其他类中的类。

顶层类:定义代码不嵌套在其他类中的类。

外部类:包含了内部类定义代码的类称为外部类。

内部类主要分为:

  成员内部类:

    与普通类相同,可以用final abstract public private protected修饰,它更像是一个成员变量和方法。

    成员内部类内不允许有任何静态声明。(生命周期不同)

    访问成员内部类的唯一途径就是通过外部类的对象。也就是说必须要有一个外部类的对象才能生成一个内部类的对象。

    外部类在非静态方法中创建内部类对象:  

public class InstanceofOuterNotStatic{
    private int i = 10;
    //声明makeInner方法,用于创建内部类,并调用seeOuter方法
    public void makeInner(){
        Inner in = new Inner();
        in.seeOuter();
    }
    class Inner{
        public void seeOuter(){
            System.out.println("外部变量:i="+i);
        }
    }
    public static void main(String[] args){
        InstanceofOuterNotStatic ins = new InstanceofOuterNotStatic();
        ins.makeInner();
    }
}

    编译运行后多出三个文件:

       

    外部类在静态方法中创建内部类对象:

    (静态方法不能访问非静态成员和方法,所以可以在这个静态方法中实例化一个外部类对象,再用这个对象实例化内部类,达到访问费静态成员和方法的目的)

public class InstanceofOuterStatic{
    private int i = 10;
    class Inner{
        public void seeOuter(){
            System.out.println("外部变量:i="+i);
        }
    }
    static public void makeInner(){
        InstanceofOuterStatic ins = new InstanceofOuterStatic();
        InstanceofOuterStatic.Inner in = ins.new Inner();
        in.seeOuter();
    }
    public static void main(String[] args){
        InstanceofOuterStatic exp = new InstanceofOuterStatic();
        exp.makeInner();
    }
}

     内部类的this引用:

      普通类可以使用this引用当前对象,内部类使用“外部类名”.this的形式实现内部类引用外部类当前的对象。

public class InnerClassThisInstance{
    class Inner{
        public void seeOuter(){
            System.out.println("i="+i);
            System.out.println("InnerClassThisInstance.this.i="+InnerClassThisInstance.this.i);
            
        }
        final int i = 10;
    }
    private int i =100;
    public static void main(String[] args){
        InnerClassThisInstance.Inner in = new InnerClassThisInstance().new Inner();
        in.seeOuter();
    }
}

  

  方法内部类:

    在类的成员方法中定义的内部类叫做方法内部类。

    它可以访问内部类的成员变量和方法、方法内的定义为final类型的局部变量、外部类的成员变量。

    (为什么只能访问方法中final类型的变量?答:在方法中定义的变量是局部变量,当方法返回时,局部变量对应的栈就被回收了,当方法内部类去访问局部变量时就会发生错误。由于不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类不允许使用局部变量。当在变量前加上final时,变量就不在是真的变量了,成了常量,这样在编译器进行编译时(即编译阶段)就会用变量的值来代替变量,这样就不会出现变量清除后,再访问变量的错误)

    方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。

public class MethodInnerClass{
    private int s = 100;
    private int a = 200;
    public void method(){
        final int s= 200;
        int k = 50;
        //方法内部类
        class Inner{
            int s = 300;
            Inner(int k){
                inner_method(k);
            }
            void inner_method(int k){
                System.out.println(s);
                System.out.println(a);
                System.out.println(k);
                //System.out.println(this.a);
                //这俩有啥不一样?
                //this.s是当前内部类中的s属性
                //MethodInnerClass.this.s是当前外部类中的s属性
                System.out.println(this.s);    
                System.out.println(MethodInnerClass.this.s);
            }
        }
        new Inner(k);
    }
    public static void main(String[] args){
        MethodInnerClass out = new MethodInnerClass();
        out.method();
    }
}

  

  匿名内部类:

    匿名内部类访问一个它外部定义的对象,这个对象必须定义为final类型。(显然这种匿名内部类实际上也是定义在外部类的某个方法中的,存在着内部类的生命周期要超过方法中局部变量的生命周期,因此匿名内部类拒绝使用局部变量~)

    匿名类只能创建一个对象。 

    匿名类有三个方式:继承式匿名内部类、接口式匿名内部类、参数试匿名内部类。

    接口式:

      一个匿名内部类只能实现一个接口。

abstract class Base{
    public Base(int i){
        System.out.println("基类构建方法,i="+i);
    }
    public abstract void method();
}
public class AnoymouseConstructor{
    public static Base getBase(int i){
        return new Base(i){
            {
                System.out.println("匿名内部类构造方法");
            }
            public void method(){
                System.out.println("匿名内部类method()方法");
            }
        };
    }
    public static void main(String[] args){
        Base base = getBase(123);
        base.method();
    }
}

    继承式:

      匿名内部类以方法参数的形式出现。

class Inner{
    public void method(){
        System.out.println("内部类inner的method");
    }
}

public class AnoymouseConstructor{
    public static void main(String[] args){
        Inner inner = new Inner(){
            public void method(){
                System.out.println("继承类Inner的method");
            }
        };
        inner.method();
    }
}

    参数式:(某个方法的参数里使用了匿名内部类)

class A{
    public A(){
        System.out.println("A中的构造方法");
    }
    public void methodA(ParameterInner f){
        f.methodB();
    }
}
//接口和抽象类都可以
abstract class ParameterInner{
    abstract void methodB();
}

public class AnoymouseConstructor{
    public static void main(String[] args){
        A a = new A();
        a.methodA(new ParameterInner(){
            public void methodB(){
                System.out.println("执行方法methodB()");
            }
        });
    }
}

    静态嵌套类:

      因为内部类和外部类具有共享外部类信息的特征,而静态嵌套类只是位于另外一个类的内部,与外部类没有信息共享的关系,所以从某种意义上来说静态嵌套类不是内部类。这里说的是不能访问非静态成员。

      静态内部类相对于外部类几乎是独立的,该嵌套类可以与其他静态成员一样在没有外部类对象的情况下也能访问它。  

class OuterClass{
    public static int i = 1;
    static class Inner{
        public Inner(){
            System.out.println("内部类的构造方法");
            System.out.println(i);
        }
    }
}

public class AnoymouseConstructor{
    public static void main(String[] args){
        OuterClass.Inner in = new OuterClass.Inner();
    }
}

 

内部类具有的共性:

  内部类仍然是一个独立的类,在编译之后他会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。

  内部类不能用普通的方式访问,它是外部类的一个成员,内部类可以自由的访问外部类的成员变量,包括private。

 

内部类的继承:

  第一种方式:

class OverloadOuterClass{
    private Inner inner;
    public OverloadOuterClass(){
        System.out.println("执行了OuterloadClass构造方法");
    }
    public void setInner(Inner inner){
        this.inner = inner;
        inner.method();
    }    
    class Inner {
        public Inner(){
            System.out.println("执行Inner构造方法");
        }
        public void method(){
            System.out.println("执行Inner.method()");
        }
    }

}

public class SubOverloadOuterClass extends OverloadOuterClass{
    public SubOverloadOuterClass(){
        setInner(new Inner());
    }
    class Inner extends OverloadOuterClass.Inner{
        public Inner(){
            System.out.println("执行重定义的inner构造方法");
        }
        public void method(){
            System.out.println("执行覆盖后的Inner.method()");
        }
    }
    public static void main(String[] args){
        new SubOverloadOuterClass();
    }
}

  第二种方式:

class BaseOuter{
    class Inner{
        Inner(){
            System.out.println("Outer.Inner构造方法");
        };
    }
}
public class InheritInner extends BaseOuter.Inner{
    //构造方法
    InheritInner(BaseOuter outer){
        outer.super();//调用BaseOuter类的构造方法
        System.out.println("InheritInner构造方法");
    }
    public static void main(String[] args){
        BaseOuter outer = new BaseOuter();
        InheritInner ii = new InheritInner(outer);
    }
}

 

以上是关于java——内部类的主要内容,如果未能解决你的问题,请参考以下文章

# Java 常用代码片段

# Java 常用代码片段

elasticsearch代码片段,及工具类SearchEsUtil.java

片段 - 全局视图变量与本地和内部类侦听器和内存泄漏

为啥片段类应该是公开的?

ForegroundService没有从片段开始?