内部类的基本介绍

内部类(累不累)

class Outer{//外部类
    private String name;//属性
    public void hi(){
        System.out.println("hi");//方法
    }

    public Outer(String name) {//构造器
        this.name = name;
    }
    {
        //代码块
    }
    //内部类
    class inner{

    }
}

内部类的分类

定义在外部类的局部位置上(方法中)定义在外部类的成员位置上
局部内部类(有类名)成员内部类(没有static修饰)
匿名内部类(没有类名【重点】)静态内部类(使用static修饰)

局部内部类

package com.LJX.InnerClass;
/*
* 演示局部内部类的使用
* */
public class localInnerclass {//外部其他类
    //不能访问 --- > 局部内部类
    public static void main(String[] args) {
        outer02 outer = new outer02();
        outer.m1();
    }
}
class outer02{//外部类
    private int n1 = 200;
    public void m1(){//方法
        //1.局部内部类定义在外部类的局部位置,通常在方法
        //3.不能添加访问修饰符,但可以使用final修饰
        //4.作用域:仅仅在定义他的方法或代码块中
        class Inner{//局部内部类(仍然是一个类)
            //2.额可以直接访问外部类的所有成员,包括私有
            private int n1 = 900;
            public void fi(){
                //5.局部内部类可以直接访问外部的成员,比如下面的n1
                //7.如果外部类与内部类重名时,遵守就近原则
                //使用 外部类的成员,用外部类名.this.成员
                //outer02.this.n1本质是外部类的对象
                //那个对象调用m1(),outer02.this.n1就是那个对象
                /*
                * 在Java中,内部类实例通常会隐式地持有一个对外部类实例的引用
                * 这是由编译器在生成字节码时自动完成的。
                * 当内部类需要引用外部类的实例时,编译器会在内部类的构造函数中添加一个对外部类实例的引用。
                * 这个引用的类型是外部类的类型,因此可以通过外部类名.this来显式地获取对外部类实例的引用。
                * */
                System.out.println("n1 = " + n1 + "外部类的n1= " + outer02.this.n1);
            }
        }
        //6.外部类访问内部类的成员,
        // 外部类在方法中,可以定义Inner对象,然后调用方法
        Inner inner = new Inner();
        inner.fi();
    }
}

匿名内部类

在Java中,匿名内部类是一种没有名称的内部类。它通常用于创建一个只需要使用一次的类的实例,并且通常作为参数传递给方法或作为接口的实现。匿名内部类通常在创建对象的同时定义类的实现,可以直接在代码中使用,而不需要单独定义一个类。它的语法形式为:new 父类或接口名() { // 匿名内部类的实现 }。使用匿名内部类可以简化代码,提高代码的可读性和可维护性。

本质
package com.LJX.InnerClass;

import com.LJX.Static_.Father;

/*
    演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        new Outer01().methods();
    }
}
class Outer01{//外部类
    private int n1 = 100;//属性
    public void methods(){
        //基于接口的匿名内部类
        //老韩解读:
        //1.需求:想使用IA接口,并创建对象
        //2.传统方式:是写一个类,并实现接口,并创建对象
        //3.老韩需求:tiger/dog 类只是使用一次,后面不再使用
        //4.可以使用匿名内部类来简化开发
        //5. tiger 的编译类型 ? IA
        //6. tiger 的运行类型 ? 就是我们的匿名内部类
        /*
        我们的系统底层会自动 分配类名 Outer01$1
           class Outer01$1 implement IA{
          @Override
          public void cry() {
              System.out.println("老虎汪汪叫....");
          }
      };
         */
        //7.jdk底层在创建匿名内部类,outer01$1,立即创建了他的实例,并把他的地址返回
        //8.匿名内部类使用一次后,就不能再使用
      IA tiger = new IA() {
          @Override
          public void cry() {
              System.out.println("老虎汪汪叫....");
          }
      };

//        IA tiger = new tiger();
//        tiger.cry();
    }
}

interface IA{//接口
    public void cry();
}
//class tiger implements IA{
//
//    @Override
//    public void cry() {
//        System.out.println("老虎汪汪叫....");
//    }
//}
//class DOg implements IA{
//    @Override
//    public void cry() {
//        System.out.println("小狗汪汪叫....");
//    }
//}
class father{
    public father(String name){//构造器

    }
    public void test(){

    }
}
package com.LJX.InnerClass;
public class A {
    public static void main(String[] args) {
        new Outer01().methods();
    }
}
class Outer01 {//外部类
    private int n1 = 100;//属性

    //基于类的匿名内部类
    //分析
    //1.p1的编译类型?father
    //2.p1的运行类型?outer01$1
    //底层会创建匿名内部类
    /*
      public void methods(){
      class outer01$2 extends father{
 public void test() { System.out.println("重写的test方法..."); }
      };
      System.out.println("p1对象的运行类型 = "+ p1.getClass());
  }
     */
    //4.返回的是匿名内部类Outer$1对象的地址
    //5.jack的值会传给构造器
    public void methods() {
        father p1 = new father("Jack") {
            //重写test方法

            @Override
            public void test() {
                System.out.println("重写的test方法...");
            }
        };
        System.out.println("p1对象的运行类型 = " + p1.getClass());
        p1.test();

        //基于抽象类的匿名内部类
        Animal p2 = new Animal() {
            //Class 'Anonymous class derived from Animal' must implement abstract method 'makesound()' in 'Animal'

            @Override
            public void makesound() {
                System.out.println("动物在叫...");
            }
        };

    }
}
class father{
    public father(String name){//构造器

    }
    public void test(){

    }
}

abstract class Animal{//抽象类
    public abstract void makesound();
}
细节
package com.LJX.InnerClass;
public class Detail01 {
    public static void main(String[] args) {
        new Outer02().f1();
    }
}
class Outer02{
    private int n1 = 100;
    public void f1() {
        //创建一个基于子类的匿名内部类
        //调用方式1
//        new person(){
//            @Override
//            public void hi() {
//                System.out.println("匿名内部类的重写 hi()");
//            }
//        }.hi();
        //第二种
        person p = new person(){
            //3.可以使用外部类的所有成员
            //4.不能添加访问修饰符,因为他的地位就是局部变量
            //5.作用域:仅仅在定义他的方法或代码块中
            //6.外部其他类不能访问匿名内部类
            //7.当外部类与内部类重名时,内部类访问遵循就近原则
            //外部类.this.成员名 来访问外部类成员
            @Override
            public void hi() {
                System.out.println("匿名内部类的重写 hi()");
            }
        };
        p.hi();

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

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

package com.LJX.InnerClass;


public class AnonymousUse {
    public static void main(String[] args) {
//        new Outer03().f1(new car());
        Outer03.f1(new IA() {
            @Override
            public void show() {
                System.out.println("boom boom bbom");
            }
        });
    }
}

class Outer03{
    private int n1 = 100;
    //传统方法,偏--->硬编码
//    public void f1(IA ia){
//        ia.show();
//    }
    //当我们这个类只需调用一次,考虑使用匿名内部类
    //静态方法,形参是接口类型
    public static void f1(IA ia){
        ia.show();
    }

}
interface IA{
    public void show() ;
}
//class car implements IA{
//    @Override
//    public void show() {
//        System.out.println("boom boom boom ...");
//    }
//}

成员内部类

package com.LJX.InnerClass;
//演示成员内部类的使用

public class NumberInnerClass {
    public static void main(String[] args) {
        Outer04 p = new Outer04();
       p.f1();
    //外部其他类使用我们的成员内部类,三种方式、
        //1.Outer04.new inner01; 相当于把 new inner01()当作是Outer的成员
        //p 是外部类的实例
        Outer04.inner01 p1 = p.new inner01();

        //2.在外部类中定义一个方法,返回inner01
       Outer04.inner01 p3 =  p.getInner01();
       p3.say();
    }
}
//7.如果外部类与内部类重名时,遵守就近原则
//使用 外部类的成员,用外部类名.this.成员
//outer04.this.n1本质是外部类的对象
class Outer04{
    private int age  = 100;
    public String name = "光头强";
    //可以添加修饰符
    public class inner01{//成员内部类
        public void say(){
            //直接访问外部类的所有成员
            System.out.println("name = " + name + "年龄" + age);
        }
    }
    //使用成员内部类
    public void f1(){
        //外部类 使用 成员内部类
        //创建成员内部类的实例,然后使用
        inner01 inter01 = new inner01();
        inter01.say();
    }
    public inner01 getInner01(){
        inner01 inner01 = new inner01();
        return inner01;
    }
}

静态内部类

package com.LJX.InnerClass;

public class StaticInnerClass {
    public static void main(String[] args) {
        //外部其他类访问------>静态内部类
        //方式1
        //因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
        Outer05.inner02 p = new Outer05.inner02();
        p.say();

        //方式2
        //编写方法,返回inner02对象
        Outer05.inner02 m2 = Outer05.m2();
        m2.say();
    }
}
class Outer05{
    private int n1 = 100;
    private static String name = "fuck";
    //inner02是静态内部类
    //使用static修饰
    //可以添加任意的修饰符
    //作用域:整个整体
   public static class inner02{
        public void say(){
            //1.可以访问所有静态成员,不能访问非静态
//            System.out.println(n1);
            String name = "大维";
            System.out.println(name);
            System.out.println("-------------------");
            //当外部类与静态内部类重名,就近原则
            //访问外部类,外部类名.成员
            System.out.println("外部类的name = " + Outer05.name);

        }
    }
    //外部类访问 ---> 静态内部类
    //先创建对象
    public void showName(){
        inner02 inner02 = new inner02();
        inner02.say();
    }

    public inner02 m1(){
      return  new inner02();
    }
    public static inner02 m2(){
        return  new inner02();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值