java_常见的四种内部类详解

简介: 局部位置调用:如果要调用,创建类对象,对象调用方法即可(方法内有内部类)作用域:方法或者代码块内

内部类的分类


局部位置


调用:如果要调用,创建类对象,对象调用方法即可(方法内有内部类)


作用域:方法或者代码块内


定义在外部类局部位置上(比如方法内,和局部变量一个层级):


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


2)匿名内部类(没有类名,重点)(JDK底层还是有名字的)


成员位置


作用域:整个类体


定义在外部类的成员位置上(和属性,方法一个层级):


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


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


1)局部内部类


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

2.局部变量是不能添加访问修饰符的,只能添加final。

3.外部类想访问内部类需要创建一个外部类对象来创建内部类对象,再由内部类对象来访问。

4.外部类和局部内部类的成员重名,默认就近原则,内部类想访问外部类重名成员,则用外部类名.this.成员,因为不是静态所以要加this(哪个对象调用方法,this则指向哪个对象)(所有内部类共享这条规则,除了静态内部


2)匿名内部类(是一个类同时是一个对象)


底层创建一个只能使用一次的类继承该类


格式:new类/接口(参数列表){类体}


(1)基于接口


传统

一般是写一个类,实现该接口,并向上转型为接口创建对象,调用接口方法。


,就会动态绑定子类的方法。


因为接口类型可以指向实现了该接口的类的对象实例。


简化开发

编译类型是接口类型,而运行类型是匿名内部类(底层系统会分配,用外部类的名称加上$1)


如果实在想看,变量名.getClass()就看到了。


接口名 变量名=new 接口名(){

       @Override

       接口方法();

};

变量名.重写后的接口方法();。

并且创建了一个实例,并把实例地址赋给变量名。


匿名内部类创建一次就不能使用了销毁了,但是那个变量地址还是可以反复使用。


(2)基于类(普通类,抽象类....)


创建对象:Person p=new Person();


编译类型:Person


运行类型:Person


创建匿名内部类:Person p=new Person(){};


编译类型:Person


运行类型:(外部类名)$(创建匿名内部类的次数)


               就是一个匿名类继承Person,所以运行类型是那个匿名类


第一种调用方式(要多次调用匿名类方法,用一个p变量接收):


Person p=new Person(){

       @Override

       类的方法(){

       }

};

p.类的方法();


第二种调用方式(只调用一次匿名内部类方法,则不需要变量接收):


new Person(){

       @Override

       类的方法(){

       super.xxx();(调用父类方法)

       }

}.类的方法();

如果一个类的构造器里面有参数,那当你基于这个类使用匿名内部类并传入参数时,会调用此类的构造器。


匿名内部类当实参传递(本质也是一个对象)

//接口
interface PP{
    //动态绑定机制
    void show();
}
//有个方法用接口类型作为参数
public static void LL(PP p){
    p.show();
}
//(1)在主方法中,用匿名内部类做一个对象,这个对象重写了show方法并传入参数
LL(new PP(){
    @Override
    //在这里改动show(),不影响其他实例
    public void show(){
        System.out.println("999999999");
    }
});
//(2)传统方法(硬编码)
LL(new Car());
//在这里改动方法show(),会影响所有Car实例
class Car implements PP{
    @Override
    public void show(){
        System.out.println("999999999");
    }
}


3)成员内部类

没有写在方法中,也不在代码块中,且没有static修饰


和上面两个相同的是,可以访问外部类的所有成员,包含私有的,


和上面两个不同的是,它可以添加任意的访问修饰符,因为地位不再是一个局部变量,而是成员变量。


外部其他类想访问成员内部类的方法


第一个方法:

则先创建一个外部类对象,再用这个对象创建一个内部类对象,再用这个内部类对象去调用方法。


第二个方法:

在外部类中定义一个方法,该方法返回一个内部类对象实例。则直接在外部类对象调用此方法即可得到一个内部类对象。。


4)静态内部类


类被声明为静态类时,必须为内部类!

反之:静态类一定是内部类!


定义在成员变量的位置,且有static修饰。


可以直接访问外部类所有静态成员(包括私有),但是不可以访问非静态成员。


可以添加任意的访问修饰符,因为地位是成员变量。


重点!!!

静态类不可以实例化!但是静态内部类可以实例化!!


外部类和局部内部类的成员重名,默认就近原则,内部类想访问外部类重名成员,则用外部类名.成员(因为你只能访问外部类静态成员,静态成员是属于类的,不需要加this)

目录
相关文章
|
2月前
|
Java
【Java基础面试二】、个Java文件里可以有多个类吗(不含内部类)?
这篇文章讨论了Java文件中类的定义规则,指出一个Java文件可以包含多个类(不包含内部类),但其中最多只能有一个public类,且如果有public类,它的名称必须与文件名一致。
|
2月前
|
算法 Java
12 Java常用类(一)(内部类+object类+包装类)
12 Java常用类(一)(内部类+object类+包装类)
30 5
|
3月前
|
Java
Java进阶之内部类
【7月更文挑战第13天】Java内部类增进代码组织与封装,允许直接访问外部类成员,包括私有成员。主要有四种类型:成员、静态、局部和匿名内部类。匿名内部类常用于一次性实现接口或扩展类。内部类可隐藏实现细节,减少命名冲突,并在特定上下文中定义辅助类。示例展示了静态和非静态内部类如何在Shape类中封装Circle和Rectangle。使用内部类能提升代码可读性,但可能增加复杂性。
34 6
|
2月前
|
Java
【Java】内部类、枚举、泛型
【Java】内部类、枚举、泛型
|
4月前
|
Java
一篇文章讲明白Java中内部类详解—匿名内部类
一篇文章讲明白Java中内部类详解—匿名内部类
63 2
|
4月前
|
设计模式 Java 编译器
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
Java中的内部类(如果想知道Java中有关内部类的知识点,那么只看这一篇就足够了!)
|
4月前
|
Java 编译器
24. 【Java教程】内部类
24. 【Java教程】内部类
25 2
|
5月前
|
Java 程序员
Java的内部类与匿名类的技术性文章
Java的内部类与匿名类的技术性文章
37 1
|
4月前
|
Java
Java内部类相关内容总结和解读
Java内部类相关内容总结和解读
29 0
|
4月前
|
存储 Java
Java 五种内部类演示及底层原理详解
Java 五种内部类演示及底层原理详解
28 0