内部类

内容很多,很麻烦,静下心慢慢看

基本介绍

一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其他类的类称为外部类

外部其他类:即其他类

特点:可以直接访问私有属性,并且可以体现类与类之间的包含关系

PS:底层源码中,有大量的内部类

基本语法

class Outer{
    class Inner{
        
    }
}
class Other{}

分类

  • 定义在外部类局部位置上(如 方法内)
  1. 局部内部类  (有类名)
  2. 匿名内部类 (没有类名)(核心)
  • 定义在外部类的成员位置上

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

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

1.局部内部类

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

②不能添加访问修饰符(属于局部变量),只能用final修饰

③作用域:仅仅在定义它的方法或代码块中

④外部类在方法中,可以创建Inner的对象,然后调用方法

⑤外部其他类不能访问局部内部类  (局部内部类,本质是是一个局部变量)

⑥若外部类和局部内部类的成员重名时,默认遵循就近原则,即使用内部类的成员。若想访问外部类的成员,可以使用

Outer.this.Method();

代码

//演示局部内部类
public class LocalInerClass {
    public static void main(String[] args) {
        Outer01 outer01 = new Outer01();
        outer01.m1();
        //  ⑤  Inner01  直接报错,外部类不能访问局部内部类

    }
}

class Outer01{
    private int n1 = 1;
    private void m2(){
        System.out.println("m2()");
    }
    public void m1(){
        System.out.println("m1()");
        //局部内部类是定义在外部类的局部位置,通常在方法中
        //可以定义在方法中
        //  ②  只能用final,默认进行修饰,不能使用别的修饰符
        final class Inner01{ //局部内部类 (本质还是一个类)
            //  ⑥  若外部类和局部内部类的成员重名时,默认遵循就近原则
            private int n1 = 2;
            public void f1(){
                //  ① 可以直接访问外部类的所有成员,包括私有
                System.out.println(n1);
                //  ⑥  若想访问外部类的成员
                System.out.println(Outer01.this.n1);
                System.out.println(Outer01.this);  // 本质是外部类的对象,即哪个对象调用m1,Outer01.this就是哪个对象,hashcode值
                m2();
            }

        }
        //  ④   外部类在创建的Inner01的方法内,调用Inner01的方法
        Inner01 inner01 = new Inner01();
        inner01.f1();
    }
    //   ③   Inner01 inner01 = new Inner01();报错  只能在作用域中调用

    //    class Inner02{}  这个不能算局部内部类,只能算内部类
    {
        //也可以定义在代码块中
        class Inner03{}
    }

}

2.匿名内部类(重点) 

实际上该类有名字,系统随机生成,但是被隐藏了,同时是一个对象

基本语法

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

需求:想使用A接口,并创建对象,且只是用一次

传统:写一个类,实现该接口,并创建对象,但不符合只使用一次的要求

故此使用匿名内部类

基于接口的匿名内部类

package chapter;

//演示匿名内部类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer01 outer01 = new Outer01();
        outer01.method();
    }
}

class Outer01{
    private int n1 = 1;
    public void method(){
        //基于接口的匿名内部类
        //tiger编译类型 A接口, 运行类型 匿名内部类
        //jdk底层在创建匿名内部类Outer01$1,立马创建实例,并把地址返回给tiger
        //注意:匿名内部类只能使用一次,但创建的对象可以使用多次
        A tiger =new A(){
            public void cry(){
                System.out.println("老虎叫");
            }
        };
        tiger.cry();
        tiger.cry();
    }
}

interface A {
    public void cry();
}
class Father{
    public Father(String name){
    }

    public void test(){}
}

基于类的匿名内部类

package chapter;

//演示匿名内部类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer01 outer01 = new Outer01();
        outer01.method();
    }
}

class Outer01{
    private int n1 = 1;
    public void method(){
        //基于类的匿名内部类
        //编译类型 Father  运行类型Outer01$2
        /*
        class Outer01$2 extends Father{}
         */
        //同时也直接返回了匿名内部类Outer01$2的对象
        //注意:("jack")参数列表会传递给 Father 构造器
        Father father = new Father("jack"){
            public void test(){
                System.out.println("匿名内部类重写了test");
            }
        };
        System.out.println(father.getClass());
        father.test();

        //基于抽象类的匿名内部类
        Animal animal =new Animal(){
            void eat(){
                System.out.println("吃");
            }
        };
        animal.eat();
    }
}

interface A {
    public void cry();
}
class Father{
    public Father(String name){
    }
    public void test(){}
}

abstract class Animal{
    abstract void eat();
}

注意

1.匿名内部类既是一个类的定义,本身又是一个对象,因此语法上看,有定义类的特征,有创建对象的特征,两种调用匿名内部类的方法

package chapter;

//演示匿名内部类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer01 outer01 = new Outer01();
        outer01.f1();
    }
}
class Person{
    public void hi(){
        System.out.println("Person hi()");
    }
    public void ok(String name){
        System.out.println("OK");
    }
}
class Outer01{
    private int n1 = 99;
    public void f1(){
        //第一种
        Person person = new Person(){
            @Override
            public void hi() {
                System.out.println("匿名内部类重写hi()");
            }
        };
        person.hi(); //动态绑定,所以输出重写后的
        person.ok("第一种调用    传参");

        //第二种    直接调用
        new Person(){
            @Override
            public void hi() {
                System.out.println("哈哈哈");
            }
        }.hi();
        //第二种的传参方法
        new Person(){
            @Override
            public void hi() {
                System.out.println("哈哈哈");
            }
        }.ok("jack");
        
    }
}

2.可以访问外部类的所有成员(同局部内部类相同)

3.作用域:仅仅在定义它的代码块或者方法中(同上)

4.外部其他类不能访问匿名内部类(同上)

5.外部类和匿名内部类重名时,默认就近原则,可访问外部类成员(同上)

使用

1.当实参进行传递

package chapter;

public class AnonymousInnerClass {
    public static void main(String[] args) {
        CellPhone cellPhone = new CellPhone();

        //1.传递的是实现了 Bell接口的匿名内部类 AnonymousInnerClass$1
        //2.重写了ring()
        //3.Bell bell = new Bell() {
        //   public void ring(){}
        //   }
        cellPhone.alarm(new Bell() {
            @Override
            public void ring() {
                System.out.println("懒猪起床");
            }
        });
        cellPhone.alarm(new Bell() {
            @Override
            public void ring() {
                System.out.println("小伙伴上课了");
            }
        });

    }
}
interface Bell{
    void ring();
}
class CellPhone{
    public void alarm(Bell bell){
        bell.ring();
    }
}

3.成员内部类

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

1.可以访问外部类的所有成员

2.可用修饰符(public protected 默认 private), 地位就是一个成员

3.作用域:与其他外部类的成员一样,为整个类体

4.可访问外部类的所有成员

5.外部类访问  成员内部类 :创建对象在访问

6.外部其他类 访问 成员内部类  (三种方式)

package chapter;

public class test {
    public static void main(String[] args) {
        
        //第一种
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        
        //第二种   外部类中编写一个方法,返回Inner的对象实例
        Outer.Inner inner1 = outer.getInner();
        
        //第三种
        Outer.Inner inner2 = new Outer().new Inner();
    }
}
class Outer{
    class Inner{}
    //第二种  所需的方法,用于返回Inner对象
    public Inner getInner(){
        return new Inner();
    }
}

7.外部类,内部类成员同名,默认就近原则(同上)

4.静态内部类

定义在外部类的成员位置,用static修饰

1.直接访问外部类的所有成员,但不能直接访问非静态成员

2.可用任意访问修饰符修饰

3.作用域:整个类体

4.外部类访问 : 创建对象在访问

5.外部其他类 访问静态内部类

第一种,通过类名直接访问(满足访问权限)

Outer.Inner inner = new Outer.Inner();
inner.method();

第二种,编写一个方法,返回静态内部类的对象实例

public class test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.getInner();
    }
}
class Outer{
    static class Inner{}
    public Inner getInner(){
        return new Inner();
    }
}

6.内外部成员重名时,默认就近原则,若想访问外部类的成员,则可以使用(外部类名.成员)

  !!!与上面略有不同,区别在于使用static修饰

测试

需改进,仅供参考

package chapter;

public class Test {
    public static void main(String[] args) {
        CellPhone p = new CellPhone();
        p.testWork(   new calcultor(){
            @Override
            public double work(double n1) {
                return 0;
            }
        },1);

    }
}
interface calcultor{
    double work(double n1);
}
class CellPhone{
    public void testWork(calcultor one,double n1){
        double result = one.work(n1);
    }
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值