Java多继承方法(名)冲突和成员内部类、局部内部类、静态内部类、匿名内部类

简介: Java内部类     ①内部类是在一个java类体内,再定义一个类,即外部类的内部再定义一个类(相对的)。      ②内部类分为四类:          成员内部类、局部内部类、静态内部类、匿名内部类      ③内部类作为外部类的一个成员,并依附于外部类而存在。包括:成员内部类、局部内部类、匿名内部类      ④内部类可以由private、public、protected

Java内部类

    内部类是在一个java类体内,再定义一个类,即外部类的内部再定义一个类(相对的)。

     ②内部类分为四类:

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

     ③内部类作为外部类的一个成员,并依附于外部类而存在。包括:成员内部类、局部内部类、匿名内部类

     ④内部类可以由private、public、protected、default访问修饰符和static修饰;

     ⑤而外部类,即和public类平行的,只能有default修饰(空白修饰符),总之,由public和default访问修饰符修饰。

     ⑥ 内部类和外部类的实例变量可以共存,

          内部类中访问实例变量:this.属性。eg: this.age

          内部类中访问外部类的实例变量:外部类名.this.属性。InnerClass.this.id

      ⑦内部类是一个编译时的概念,编译成功,就会成为完全不同的两个类  eg:InnerClass.class和InnerClass$Classx1.class

      ⑧内部类里不能定义静态的属性和方法;

          注:此处内部类(除静态内部类外);

         加载类时,静态默认在内存中实例化的并存放。即可以直接调用不用手动实例化使用。内部类的实例化依赖于外部类,内部类不能直接被实例化,必须在外部类实例化后再实例化。

         外部类public class或class是不能默认加载的,只有调用new关键字手动实例化时才分配内存。

         所以内部类不能定义静态的属性和方法。

所有代码编译图为:

成员内部类:

package com.classx.inner;

public class InnerClass {
    //外部类private属性
    private int id=4466;
    private static String name ="shasha";
    //外部类getter和setter方法
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public static String getName() {
        return name;
    }
    public static void setName(String name) {
        InnerClass.name = name;
    }
    //************************成员内部类***********************************//
    //成员内部类,作为外部类的成员,可以访问外部所有
    //内部类中的定义的private属性,比外部的private还小的访问权限
    //作为一个外部类的成员存在,和外部类的属性、方法并列
    //可以有private、public、protected、default修饰
     class Classx1{
        private int age=5555;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        } 
        public void getN1(){
            System.out.println("inner1");
            System.out.println("成员内部类:"+InnerClass.this.id+"*"+this.age);
        }
    }
     //外部类内部调用成员内部类
     public void getC1(){
         Classx1 c1 = new Classx1();
         c1.getN1();
         System.out.println("外部类内部调用成员内部类:完毕!");
     }
}

测试类:

package com.classx.inner;


public class Test {
    public static void main(String[] args) {

        //*****外部类调用成员内部类********//
        //外部类对象ic
        InnerClass ic = new InnerClass();
        
        /***成员内部类***/
        //内部调用
        ic.getC1();
        //外部调用
//        InnerClass.Classx1 icc1 = new InnerClass().new Classx1();
        InnerClass.Classx1 icc1 = ic.new Classx1();
        icc1.getN1();
    }
}

输出结果:

inner1
成员内部类:4466*5555
外部类内部调用成员内部类:完毕!
inner1
成员内部类:4466*5555

编译后的class字节码反编译为:

InnerClass类:

package com.classx.inner;

import java.io.PrintStream;

public class InnerClass
{
  private int id = 4466;
  private static String name = "shasha";

  public int getId() {
    return this.id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public static String getName() {
    return name;
  }
  public static void setName(String name) {
    name = name;
  }

  public void getC1()
  {
    Classx1 c1 = new Classx1();
    c1.getN1();
    System.out.println("外部类内部调用成员内部类:完毕!");
  }

  class Classx1
  {
    private int age = 5555;

    Classx1() {  } 
    public int getAge() { return this.age; }

    public void setAge(int age) {
      this.age = age;
    }
    public void getN1() {
      System.out.println("inner1");
      System.out.println("成员内部类:" + InnerClass.this.id + "*" + this.age);
    }
  }
}

成员内部类Classx1:

package com.classx.inner;

import java.io.PrintStream;

class InnerClass$Classx1
{
  private int age = 5555;

  InnerClass$Classx1(InnerClass paramInnerClass) {  } 
  public int getAge() { return this.age; }

  public void setAge(int age) {
    this.age = age;
  }
  public void getN1() {
    System.out.println("inner1");
    System.out.println("成员内部类:" + InnerClass.access$0(this.this$0) + "*" + this.age);
  }
}

局部内部类:

此后外部类代码,不变,替换内部类:

   //************************局部内部类***********************************//
    public void drawIC(){
        //在外部类方法体中定义的类叫局部内部类,不能有修饰符(包括static),能访问外部类实例变量,且只能访问方法体中的final类型的局部变量
        final String fstr = "lalala";
        System.out.println("inner2");
        //局部内部类
        //外部类外不可直接生成局部内部类,对外不可见
        class Classx2{
            private int width = 333;
            public Classx2(){
                super();
                System.out.println("局部内部类默认构造方法在drawIC中new时候执行");
            }
            public void getN2(){
                System.out.println("局部内部类:"+fstr+"&"+id+"$"+width);
            }
        }
        //使用局部内部类,要生成对象,对象调用方法,在方法中才能调用其局部内部类
        //局部内部类使用new,方法调用
        Classx2 icmc = new Classx2();
        System.out.println("局部内部类对象调用getN2开始");
        icmc.getN2();
    }

测试代码:

此后,main中的代码,其他省略:

        //*****外部类调用成员内部类********//
        //外部类对象ic
        InnerClass ic = new InnerClass();

        /***局部内部类***/
        //调用局部内部类
        ic.drawIC();

代码输出为:

inner2
局部内部类默认构造方法在drawIC中new时候执行
局部内部类对象调用getN2开始
局部内部类:lalala&4466$333

编译后的InnerClass类:

此后,只替换变化代码,其他不变:

  public void drawIC()
  {
    String fstr = "lalala";
    System.out.println("inner2");

    Object icmc = new Object()
    {
      private int width = 333;

      public void getN2()
      {
        System.out.println("局部内部类:lalala&" + InnerClass.this.id + "$" + this.width);
      }
    };
    System.out.println("局部内部类对象调用getN2开始");
    icmc.getN2();
  }

编译后的Classx2类:

package com.classx.inner;

import java.io.PrintStream;

class InnerClass$1Classx2
{
  private int width = 333;

  public InnerClass$1Classx2(InnerClass paramInnerClass) {
    System.out.println("局部内部类默认构造方法在drawIC中new时候执行");
  }
  public void getN2() {
    System.out.println("局部内部类:lalala&" + InnerClass.access$0(this.this$0) + "$" + this.width);
  }
}

静态内部类

    //************************静态内部类***********************************//
    //静态内部类
    //外部类只能有public和default修饰符,而成员内部类可以有private、public、protected、default和static修饰
    //只能访问外部类静态成员
    public static class Class3{
       private static int length = 169;
       public void getN3(){
           System.out.println("inner3");
           System.out.println("静态内部类:"+length+InnerClass.name);
       }
    }

测试代码:

        /***静态内部类***/
        //调用静态内部类
        //不需要通过生成外部类的对象来生成,实际上,成为了顶级类
//        Class3 c3 = new InnerClass.Class3();
        InnerClass.Class3 c3 = new InnerClass.Class3();
        c3.getN3();


输出为:

inner3
静态内部类:169shasha

编译后:

InnerClass类:

  public static class Class3
  {
    private static int length = 169;

    public void getN3() { System.out.println("inner3");
      System.out.println("静态内部类:" + length + InnerClass.name);
    }
  }

Class3类:

package com.classx.inner;

import java.io.PrintStream;

public class InnerClass$Class3
{
  private static int length = 169;

  public void getN3() { System.out.println("inner3");
    System.out.println("静态内部类:" + length + InnerClass.access$0());
  }
}

匿名内部类:

In接口:

package com.classx.inner;

public interface In {
    public abstract int extend();
}

Ac抽象类:

package com.classx.inner;

public abstract class Ac {
    public abstract int extend();
}

InnerClass类:

    //************************匿名内部类***********************************//
    //匿名内部类
    //①是特殊的局部内部类,所以局部内部类的限制对它生效,不能有访问修饰符和static修饰
    //②唯一一个无构造方法的类(使用范围很有限),不能定义任何静态成员、方法、类
    //③一个匿名内部类一定是在new后面,用它隐含的实现一个接口或实现一个类
    //④没有类名(不能有),所以不能引用它。根据多态,可使用它的父类(接口)名
    //⑤没办法引用它,必须在创建时,作为new语句的一部分来声明它(特殊形式new语句),形式:new 类名或接口名(){类的主体}
    //通过上new语句声明形式,声明一个新的匿名类,它对一个给定类进行扩展,或实现一个给定的接口
    //并且还创建给定类或给定接口的新实例(只能创建匿名内部类的一个实例),并把它作为语句的结果返回
    //⑥内部匿名类,就是建立一个内部的类,但没有给你命名,也就是没有引用实例的变量。
    //⑦匿名类扩展了给定类,可以访问该被扩展类的成员、覆盖它的方法等(标准类一致)
    //⑧匿名类实现了接口,它的主体必须实现接口的方法
    //⑨如果一个对象编译时类型为接口,那么运行时类型为实现这个接口的类
    //10编译时系统自动起名:InnerClass$1.class
    
    //*匿名内部类实现一个接口,可以解决多继承出现方法冲突问题*/
    //可以直接返回return,也可作为方法返回值(给定接口或类的实例)返回
    public In getExtendI(){
        return new In() {
            @Override
            public int extend() {
                System.out.println("inner4");
                System.out.println("匿名内部类:我实现了接口In的方法");
                return 0;
            }
        };
    }
    //一般new对象,InnerClass ic = new InnerClass();
    //小括号后为;分号,结束,即new出了对象语句结束
    //匿名内部类,new In() {...}
    //小括号后为{}大括号,大括号中是该new出对象的具体实现方法
    //一个抽象类不能直接使用(new对象),不能生成对象,必须继承使用,后进行new出对象使用
    //*匿名内部类,可以对抽象类进行实现(实现类为匿名内部类),和extends继承父类,实现抽象是一样的 */
    public Ac getExtendC(){
        return new Ac() {
            @Override
            public int extend() {
                System.out.println("inner5");
                System.out.println("匿名内部类:我扩展了抽象类AC的方法"+(InnerClass.this.id));
                return 0;
            }
        };
    }
    //*匿名内部类不能对InnerClass类扩展,方法不可用"unused"*/

测试类:

        /***匿名内部类***/
        //匿名内部类实现接口的调用
        In in = ic.getExtendI();
        in.extend();
        //匿名内部类作为抽象类的实现类
        Ac ac = ic.getExtendC();
        ac.extend();

输出结果:
 inner4
匿名内部类:我实现了接口In的方法
inner5
匿名内部类:我扩展了抽象类AC的方法4466

编译后:

InnerClass类:

public In getExtendI()
  {
    return new In()
    {
      public int extend() {
        System.out.println("inner4");
        System.out.println("匿名内部类:我实现了接口In的方法");
        return 0;
      }
    };
  }

  public Ac getExtendC()
  {
    return new Ac()
    {
      public int extend() {
        System.out.println("inner5");
        System.out.println("匿名内部类:我扩展了抽象类AC的方法" + InnerClass.this.id);
        return 0;
      }
    };

接口实现匿名内部类:

package com.classx.inner;

import java.io.PrintStream;

class InnerClass$1
  implements In
{
  InnerClass$1(InnerClass paramInnerClass)
  {
  }

  public int extend()
  {
    System.out.println("inner4");
    System.out.println("匿名内部类:我实现了接口In的方法");
    return 0;
  }
}

抽象类实现类(匿名内部类)

package com.classx.inner;

import java.io.PrintStream;

class InnerClass$2 extends Ac
{
  InnerClass$2(InnerClass paramInnerClass)
  {
  }

  public int extend()
  {
    System.out.println("inner5");
    System.out.println("匿名内部类:我扩展了抽象类AC的方法" + InnerClass.access$0(this.this$0));
    return 0;
  }
}

注:最尾提供全部代码


Java多继承方法(名)冲突

当类或接口或(抽象)父类,三个不同组合,发生方法(名)冲突的时候,此时必须使用内部类来解决。

匿名内部类、成员内部类
接口配合内部类,可以实现真正完全的多继承。

接口In:

package com.classx.inner;

public interface In {
    public abstract int extend(int id);
}

抽象类Ac:

package com.classx.inner;

public abstract class Ac {
    public abstract int extend(int id);
}

实现类InnerClassSolveMultipleForAcOrIn:

package com.classx.inner;


//当类或接口或(抽象)父类,三个不同组合,发生方法(名)冲突的时候,此时必须使用内部类来解决
//接口配合内部类,可以实现真正完全的多继承
public class InnerClassSolveMultipleForAcOrIn implements In{
    public int id = 3355;
    @Override
    public int extend(int id) {
        System.out.println("外部类实现接口In中的extend()方法"+id);
        return 1;
    }
    //内部类作为外部类的成员(非静态)
    //内部类可以对外部类状态完全进行修改,和直接调用(使用)InnerClassSolveMultipleForAcOrIn是一样的
    private class InnerC extends Ac{
        @Override
        public int extend(int id) {
            System.out.println("成员内部类实现抽象父类Ac中的extend()方法"+id);
            return 2;
        }
    }
    //内部类为private的,除了当前外部类,其他类都是不可见的
    //而此方法,返回值为直接向上转型(实现了抽象父类)的抽象父类的引用,对外暴露抽象父类,隐藏了InnerC的存在
    public Ac getInnerCInstance(){
        return new InnerC();
    }
    //匿名内部类解决冲突
    public Ac getgetInnerNoInstance(){
        return new Ac() {
            @Override
            public int extend(int id) {
                System.out.println("匿名内部类实现抽象父类Ac中的extend()方法"+id);
                return 3;
            }
        };
    }
}

测试类:

package com.classx.inner;


public class TestAcIn {
    public static void main(String[] args) {
        //外部类对象
        InnerClassSolveMultipleForAcOrIn iaci = new InnerClassSolveMultipleForAcOrIn();
        In in = iaci;
        //外部类实现接口方法
        in.extend(1);
        
        //用"成员内部类"解决(实现)抽象类和接口同名方法
        Ac ac = iaci.getInnerCInstance();
        ac.extend(2);
        
        //用"匿名内部类"解决(实现)抽象类和接口同名方法
        Ac acn = iaci.getgetInnerNoInstance();
        acn.extend(3);
    }
    
}

输出结果:

外部类实现接口In中的extend()方法1
成员内部类实现抽象父类Ac中的extend()方法2
匿名内部类实现抽象父类Ac中的extend()方法3

 

实现内部类,全部代码:

内部类InnerClass代码:

package com.classx.inner;

public class InnerClass {
    //外部类private属性
    private int id=4466;
    private static String name ="shasha";
    //外部类getter和setter方法
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public static String getName() {
        return name;
    }
    public static void setName(String name) {
        InnerClass.name = name;
    }
    //************************成员内部类***********************************//
    //成员内部类,作为外部类的成员,可以访问外部所有
    //内部类中的定义的private属性,比外部的private还小的访问权限
    //作为一个外部类的成员存在,和外部类的属性、方法并列
    //可以有private、public、protected、default修饰
     class Classx1{
        private int age=5555;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        } 
        public void getN1(){
            System.out.println("inner1");
            System.out.println("成员内部类:"+InnerClass.this.id+"*"+this.age);
        }
    }
     //外部类内部调用成员内部类
     public void getC1(){
         Classx1 c1 = new Classx1();
         c1.getN1();
         System.out.println("外部类内部调用成员内部类:完毕!");
     }
   //************************局部内部类***********************************//
    public void drawIC(){
        //在外部类方法体中定义的类叫局部内部类,不能有修饰符(包括static),能访问外部类实例变量,且只能访问方法体中的final类型的局部变量
        final String fstr = "lalala";
        System.out.println("inner2");
        //局部内部类
        //外部类外不可直接生成局部内部类,对外不可见
        class Classx2{
            private int width = 333;
            public Classx2(){
                super();
                System.out.println("局部内部类默认构造方法在drawIC中new时候执行");
            }
            public void getN2(){
                System.out.println("局部内部类:"+fstr+"&"+id+"$"+width);
            }
        }
        //使用局部内部类,要生成对象,对象调用方法,在方法中才能调用其局部内部类
        //局部内部类使用new,方法调用
        Classx2 icmc = new Classx2();
        System.out.println("局部内部类对象调用getN2开始");
        icmc.getN2();
    }
    //************************静态内部类***********************************//
    //静态内部类
    //外部类只能有public和default修饰符,而成员内部类可以有private、public、protected、default和static修饰
    //只能访问外部类静态成员
    public static class Class3{
       private static int length = 169;
       public void getN3(){
           System.out.println("inner3");
           System.out.println("静态内部类:"+length+InnerClass.name);
       }
    }
    //************************匿名内部类***********************************//
    //匿名内部类
    //①是特殊的局部内部类,所以局部内部类的限制对它生效,不能有访问修饰符和static修饰
    //②唯一一个无构造方法的类(使用范围很有限),不能定义任何静态成员、方法、类
    //③一个匿名内部类一定是在new后面,用它隐含的实现一个接口或实现一个类
    //④没有类名(不能有),所以不能引用它。根据多态,可使用它的父类(接口)名
    //⑤没办法引用它,必须在创建时,作为new语句的一部分来声明它(特殊形式new语句),形式:new 类名或接口名(){类的主体}
    //通过上new语句声明形式,声明一个新的匿名类,它对一个给定类进行扩展,或实现一个给定的接口
    //并且还创建给定类或给定接口的新实例(只能创建匿名内部类的一个实例),并把它作为语句的结果返回
    //⑥内部匿名类,就是建立一个内部的类,但没有给你命名,也就是没有引用实例的变量。
    //⑦匿名类扩展了给定类,可以访问该被扩展类的成员、覆盖它的方法等(标准类一致)
    //⑧匿名类实现了接口,它的主体必须实现接口的方法
    //⑨如果一个对象编译时类型为接口,那么运行时类型为实现这个接口的类
    //10编译时系统自动起名:InnerClass$1.class
    
    //*匿名内部类实现一个接口,可以解决多继承出现方法冲突问题*/
    //可以直接返回return,也可作为方法返回值(给定接口或类的实例)返回
    public In getExtendI(){
        return new In() {
            @Override
            public int extend() {
                System.out.println("inner4");
                System.out.println("匿名内部类:我实现了接口In的方法");
                return 0;
            }
        };
    }
    //一般new对象,InnerClass ic = new InnerClass();
    //小括号后为;分号,结束,即new出了对象语句结束
    //匿名内部类,new In() {...}
    //小括号后为{}大括号,大括号中是该new出对象的具体实现方法
    //一个抽象类不能直接使用(new对象),不能生成对象,必须继承使用,后进行new出对象使用
    //*匿名内部类,可以对抽象类进行实现(实现类为匿名内部类),和extends继承父类,实现抽象是一样的 */
    public Ac getExtendC(){
        return new Ac() {
            @Override
            public int extend() {
                System.out.println("inner5");
                System.out.println("匿名内部类:我扩展了抽象类AC的方法"+(InnerClass.this.id));
                return 0;
            }
        };
    }
    //*匿名内部类不能对InnerClass类扩展,方法不可用"unused"*/
}

测试Test代码:

package com.classx.inner;


public class Test {
    public static void main(String[] args) {

        //*****外部类调用成员内部类********//
        //外部类对象ic
        InnerClass ic = new InnerClass();
        
        /***成员内部类***/
        //内部调用
        ic.getC1();
        //外部调用
//        InnerClass.Classx1 icc1 = new InnerClass().new Classx1();
        InnerClass.Classx1 icc1 = ic.new Classx1();
        icc1.getN1();
        
        /***局部内部类***/
        //调用局部内部类
        ic.drawIC();
        
        /***静态内部类***/
        //调用静态内部类
        //不需要通过生成外部类的对象来生成,实际上,成为了顶级类
//        Class3 c3 = new InnerClass.Class3();
        InnerClass.Class3 c3 = new InnerClass.Class3();
        c3.getN3();
        
        /***匿名内部类***/
        //匿名内部类实现接口的调用
        In in = ic.getExtendI();
        in.extend();
        //匿名内部类作为抽象类的实现类
        Ac ac = ic.getExtendC();
        ac.extend();
    }
}

输出结果:

inner1
成员内部类:4466*5555
外部类内部调用成员内部类:完毕!
inner1
成员内部类:4466*5555
inner2
局部内部类默认构造方法在drawIC中new时候执行
局部内部类对象调用getN2开始
局部内部类:lalala&4466$333
inner3
静态内部类:169shasha
inner4
匿名内部类:我实现了接口In的方法
inner5
匿名内部类:我扩展了抽象类AC的方法4466


package com.classx.inner;


public class Test {
    public static void main(String[] args) {

        //*****外部类调用成员内部类********//
        //外部类对象ic
        InnerClass ic = new InnerClass();
        
        /***成员内部类***/
        //内部调用
        ic.getC1();
        //外部调用
//        InnerClass.Classx1 icc1 = new InnerClass().new Classx1();
        InnerClass.Classx1 icc1 = ic.new Classx1();
        icc1.getN1();
        
        /***局部内部类***/
        //调用局部内部类
        ic.drawIC();
        
        /***静态内部类***/
        //调用静态内部类
        //不需要通过生成外部类的对象来生成,实际上,成为了顶级类
//        Class3 c3 = new InnerClass.Class3();
        InnerClass.Class3 c3 = new InnerClass.Class3();
        c3.getN3();
        
        /***匿名内部类***/
        //匿名内部类实现接口的调用
        In in = ic.getExtendI();
        in.extend();
        //匿名内部类作为抽象类的实现类
        Ac ac = ic.getExtendC();
        ac.extend();
    }
}


 

 


 

目录
相关文章
|
13天前
|
Java
Java中ReentrantLock中tryLock()方法加锁分析
Java中ReentrantLock中tryLock()方法加锁分析
12 0
|
2天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
23 3
|
4天前
|
存储 Java
Java动态转发代理IP的实现方法
Java动态转发代理IP的实现方法
20 11
|
5天前
|
Java
Java接口中可以定义哪些方法?
【4月更文挑战第13天】
7 0
Java接口中可以定义哪些方法?
|
11天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
12 0
|
11天前
|
安全 Java 编译器
接口之美,内部之妙:深入解析Java的接口与内部类
接口之美,内部之妙:深入解析Java的接口与内部类
33 0
接口之美,内部之妙:深入解析Java的接口与内部类
|
13天前
|
Java
Java中关于ConditionObject的signal()方法的分析
Java中关于ConditionObject的signal()方法的分析
21 4
|
13天前
|
安全 Java
append在Java中是哪个类下的方法
append在Java中是哪个类下的方法
21 9
|
13天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
13天前
|
存储 Java
java接口和内部类
java接口和内部类