java学习日记20230325-内部类

内部类

 基本介绍:

  一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类(inner class),嵌套其他类的类车称为外部类(outer class),是我们类的第五大成员(属性,方法,构造器,代码块,内部类),内部类最大的特点就是可以直接访问私有属性,并且可以提现类与类之间的包含关系。内部类是学习的难点和重点,底层源码又大量的内部类

  基本语法

  

复制代码
class Outer{//外部类
    
    class Inner{//内部类

    }

}

class Other{//其他类

}
复制代码

内部类的分类:

  定义在外部类局部位置上(比如方法内):

  1.局部内部类(有类名)

    • 可以直接访问外部类的所有成员,包含私有的;
    • 不能添加访问修饰符,因为他的地位就是一个局部变量,局部变量是不能使用修饰符的,但是 可以使用final修饰了因为局部变量也可以使用final
    • 作用域,仅仅在定义他的方法或代码块中
    • 局部内部类--访问--外部类的成员(直接访问)
    • 外部类--访问--局部内部类的成员 访问方式:创建对象,再访问(必须在作用域内)
    • 局部内部类定义在方法中/代码块
    • 作用域在方法体和代码块中
    • 本质是一个类
    • 外部其他类--不能访问--局部内部类
    • 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员 相当于调用方法的对象)去访问
    • 复制代码
      public class InnerClass01 {
          public static void main(String[] args) {
              Outer outer = new Outer(100);
              outer.m1();
          }
      }
      
      class Outer{
          private  int n1 =100;
      
          public Outer(int n1) {
              this.n1 = n1;
          }
          public void m1(){
              System.out.println("m1");
              //int n1 = 1000;
              class Inner{
                  //private int n1 = 10000;
                  public void fun(){
                      System.out.println(n1 +"fun内部类调用");
                  }
              }
              Inner inner = new Inner();
              inner.fun();
          }
          {
              System.out.println("代码块");
          }
          class Inner{//内部类
      
          }
      }
      View Code
      复制代码

       

  2.匿名内部类(无类名)

    匿名内部类的基本用法:

    new 类或者接口(参数列表){类体};

    本质是类,是个内部类,该类没有名字(名字由jvm分配),同时是一个对象

基于接口的代码案例:  参数列表会传递给构造器  

复制代码
public class AnonymousInterfaceClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.m2();
    }
}

class Outer04 implements A{
    private int n1 = 10;

    @Override
    public void cry() {
        System.out.println("老虎叫");
    }

    public void m2(){
        //tiger的编译类型是接口IA,tiger的运行类型是匿名类型
        A tiger =new A(){
            @Override
            public void cry() {
                System.out.println("老虎叫");
            }
        };
        //jdk底层创建匿名内部类Outer04$1,立马创建Outer04$1实例,并且把地址返回给tiger
        //匿名内部类使用一次就不能再使用
        System.out.println(tiger.getClass());//class com.study.anonymousinterface.Outer04$1
        tiger.cry();
        tiger.cry();
        tiger.cry();
    }
}

interface  A{
    public void cry();
}
View Code
复制代码

基于类的代码案例:

  

复制代码
public class AnonymousInterfaceClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.m2();
    }
}

class Outer04 implements A{
    private int n1 = 10;

    @Override
    public void cry() {
        System.out.println("老虎叫");
    }

    public void m2(){
        //tiger的编译类型是接口IA,tiger的运行类型是匿名类型
        A tiger =new A(){
            @Override
            public void cry() {
                System.out.println("老虎叫");
            }
        };
        //jdk底层创建匿名内部类Outer04$1,立马创建Outer04$1实例,并且把地址返回给tiger
        //匿名内部类使用一次就不能再使用
        System.out.println(tiger.getClass());//class com.study.anonymousinterface.Outer04$1
        tiger.cry();

        Father father = new Father("jack"){
            @Override
            public void getSon() {
                super.getSon();
                System.out.println("或者女儿");
            }
        };
        System.out.println(father.getClass());//class com.study.anonymousinterface.Outer04$2
        father.getSon();
    }
}

interface  A{
    public void cry();
}

class Father{
    private String name;

    public Father(String name) {
        this.name = name;
    }

    public void getSon(){
        System.out.println("获取儿子");
    }
}
View Code
复制代码

匿名内部类使用细节:

  • 匿名内部类的语法比较奇特,因为匿名内部类即时一个类的定义,同时它本身也是一个对象爱过你,因此从语法上看,他既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法

  

复制代码
public class AnonymousInnerInterfaceDetail {
    public static void main(String[] args) {
        Outer05 outer05 = new Outer05();
        outer05.f1();
    }
}

class Person{
    public void hi(){
        System.out.println("person hi()");
    }

    public void ok(String str){
        System.out.println("ok()"+str);
    }
}

class Outer05{
    private  int n1 =99;
    public void f1(){
        Person person =new Person(){
            @Override
            public void hi() {
                System.out.println("匿名内部类重写了hi方法");
            }

            @Override
            public void ok(String str) {
                super.ok(str);
            }
        };
        person.hi();
        person.ok("123");
        new Person(){
            @Override
            public void hi() {
                System.out.println("匿名内部类重写了hi方法1");
            }
        }.hi();

    }
}
View Code
复制代码

  

  • 匿名内部类可以直接访问外部类的所有成员,包含私有的
  • 不能添加访问修饰符,因为他的地位就是一个局部变量
  • 作用域,仅仅在定义他的方法或代码块中
  • 匿名内部类--访问---外部类成员,直接访问
  • 外部其他类不能访问匿名内部类
  • 外部类和匿名内部类属性重名时,按照就近原则,如果需要访问外部类的属性,可以使用 类名.this.属性名

匿名内部类使用场景:

  当做实参直接传递,高效简洁

  

复制代码
public class InnerClassExercise02 {
    public static void main(String[] args) {
        Cellphone cellphone = new Cellphone();
        //传递的是实现了bell接口的匿名内部类,重写了ring,bell接收了匿名内部类创建的对象
        //利用动态绑定机制,执行重写的ring方法
        cellphone.alarmclock(new Bell() {
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });
    }
}


interface Bell{
     void ring();
}

class Cellphone{
    public void alarmclock(Bell bell){

        bell.ring();
    }
}
View Code
复制代码

  

    

  定义在外部类的成员位置上:

  1.成员内部类(没用static修饰)

    成员内部类是定义在外部类的成员位置,并且没有static修饰

    1.可以直接访问外部类的所有成员,包括私有的;

    2.可以添加任意访问修饰符,因为他的地位是一个成员

    3.和外部类的其他成员一样,在外部类的成员方法中创建成员内部类对象,在调用方法;

    4.成员内部类--访问--外部类 直接访问

    5.外部类--访问--内部类,创建对象,访问

    6.外部其他类--访问--成员内部类

    7.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问 

    

复制代码
public class MemberInnerClass {
    public static void main(String[] args) {
        Outer08 outer08 = new Outer08();
        outer08.t1();

        //外部其他类,使用成员内部类,第一种
        Outer08.Inner8 outer081 = outer08.new Inner8();
        outer081.say();

        //第二种
        outer08.getInner().say();

    }
}

class Outer08{
    private int n1 =100;
    public String name = "jack";
    public class Inner8{
        private int n1 = 10000;
        public void say(){
            System.out.println(n1+name+Outer08.this.n1);
        }
    }

    public void t1(){

        //创建成员内部类对象,使用对象属性和方法
        Inner8 inner8 = new Inner8();
        inner8.say();
        System.out.println(inner8.n1);
    }

    public Inner8 getInner(){
        return new Inner8();
    }
}
View Code
复制代码

 

  2.静态内部类(使用static修饰)

    静态内部类是定义在外部类的成员位置,并且有static修饰

    1.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员;

    2.可以添加任意 访问修饰符

    3.作用域同其他成员,为整个类体

    4.静态内部类--访问--外部类 直接访问所有静态成员

    5.外部类--访问--静态内部类。创建内部对象,再访问

    6.外部其他类--访问--静态内部类

    7.如果外部类和静态内部类的成员重名时,静态内部类访问遵循就近原则,如果想访问外部类的成员,则可以使用,外部类名.成员去访问

    

复制代码
public class StaticMemberInnerClass {
    public static void main(String[] args) {
        Outer10 outer10 = new Outer10();
        outer10.m1();

        //外部类访问
        Outer10.Inner10 inner10 = new Outer10.Inner10();
        outer10.get();
    }
}


class Outer10{

    private int n1 =100;
    private static int n2 = 1000;

    private static void cry(){
        System.out.println("cry");
    }

    public static class Inner10{
        public void say(){
            System.out.println(n2);
            cry();
            Outer10.cry();
        }

        public void cry(){
            System.out.println("内部类cry");
        }
    }

    public void m1(){
        Inner10 inner10 = new Inner10();
        inner10.say();
    }

    public Inner10 get(){
        return new Inner10();
    }
}
View Code
复制代码

 

posted @   、子夜  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
点击右上角即可分享
微信分享提示