程序地带

内部类


成员内部类(实例内部类)

成员内部类是最普通的内部类,它的定义为位于另一个类的内部


总结
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。 如果要访问外部类的同名成员,需要以下面的形式进行访问: 外部类.this.成员变量 外部类.this.成员方法
class Circle {
private double radius = 10;
public static int count =11;
class Draw { //内部类
public void drawSahpe() {
private double radius = 100;
public static int count =111;
System.out.println(this.radius); //打印100-内部类的private成员
System.out.println(count); //打印111-内部类的静态成员
System.out.println(Circle.this.radius);//打印10-外部类的radius
System.out.println(Circle.this.count);//打印11-外部类的count
}
}
}
在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。

缘由


Java 编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部 类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。


public class Test {
public static void main(String[] args) {
//第一种方式:
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建
//第二种方式:
Outter.Inner inner1 = outter.getInnerInstance();
}
}
class Outter {
public Inner getInnerInstance() {
if(inner == null)
inner = new Inner();
return inner;
}
//内部类
class Inner {
}
}
注意
实例内部类当中,是不可以定义静态的成员变量的。

如果要非要定义,那么只有一个办法。 static final 修饰,此时定义的变量如果是静态的,一定是在编译时期就能确定其值的。


实例内部类,是否有额外的开销?

有额外开销,因为内部类中包含了外部类的 this。 Inner是Outer的 成员 Outer .this->拿到外部类名.this拿到外部类的引用。可以在内部类中访问到外部类的对象。因为用类名可以 . 证明是一个静态的。this从本质上说是静态的


一个class会生成一个class文件。java高效率,使用哪一个才会去加载。

内部类生成的字节码文件文件名是:Outer$Inner.class


命名

大驼峰命名


静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static



静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问。
如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员。
创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
public class TestInnerClass {
public static void main(String[] args) {
//定义内部类对象
OuterClass.InnerClass innerClass = new OuterClass.InnerClass(new OuterClass());
innerClass.func2();
}
}
class OuterClass {
public int data1 = 9;
public static int data2=10;
static class InnerClass {
public int data1 = 99;
public static int data2=100;
//提供一个外部类对象的引用就可以访问外部类的成员变量
OuterClass outerClass;
public InnerClass(OuterClass outerClass){
this.outerClass=outerClass;
}
public void func2() {
System.out.println("内部类的成员变量data1:"+data1);
System.out.println("内部类的成员变量data1:"+this.data1);
System.out.println("内部类的静态成员变量data2:"+data2);
System.out.println("内部类的静态成员变量data2:"+InnerClass.data2);
System.out.println("外部类的静态成员变量data2:"+OuterClass.data2);
System.out.println("外部类的成员变量data1:"+this.outerClass.data1);
}
}
}
注意

1.如何拿到静态内部类的实例对象? 外部类名 . 静态内部类名 in = new 外部类类名 . 内部类(); 静态的内部类,访问外部的静态量。我们只需要使用OuterClass2.InnerClass2 .即可。 2.静态内部类能否访问外部类的成员? 可以直接访问到外部类的静态成员,不能直接访问实例成员但可以间接进行访问, 访问方法,我们在内部类中建一个带一个参数的构造方法, 只要提供给他外部类的对象的引用就好了


匿名内部类/局部内部类

匿名类是不能有名称的类,所以没办法引用他们。必须在创建时,作为new语句的一部分来声明他们


public class TestInnerClass {
public static void main(String[] args) {
new OuterClass(){//匿名内部类
public void eat(){
System.out.println("我重写了eat()");
}
};
new OuterClass(){//匿名内部类直接调用方法
public void eat(){
System.out.println("我重写了eat()");
}
}.fun();
OuterClass outerClass= new OuterClass(){//匿名内部类-引用调用
public void eat(){
System.out.println("我重写了eat()");
}
};
outerClass.eat();
}
}
class OuterClass {
public void eat(){
System.out.println("eat()");
}
public void fun(){
System.out.println("fun()");
}
}

使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。匿名内部类中是不能定义构造函数的。匿名内部类中不能存在任何的静态成员变量和静态方法。匿名内部类为局部内部类(即方法内部类),所以局部内部类的所有限制同样对匿名内部类生效。匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。匿名类的声明是在编译时进行的,实例化在运行时进行
注意
如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为 final 。

在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。 简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。 故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。 参考博文:https://blog.51cto.com/android/384844


局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。


class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}
注意

由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。


内部类的好处
每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。方便编写事件驱动程序。方便编写线程代码。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_45630711/article/details/112689308

随机推荐

Axure中后台管理信息系统通用原型

本期给大家分享的是一套完整的模板:Axure中后台管理信息系统通用原型首先是登陆页面以及登录框架,一共有12个登陆界面及登录框架供你选择:接着就是系统界面&#...

Ares丶茂 阅读(245)

centos查看历史指令记录_Linux常用指令

常用指令1、帮助指令man[指令或者配置文件]help指令2、文件目录类指令1、pwd功能:显示当前工作目录的绝对路径2、ls[选项][目录或者文件]功能:列出文件名和目录...

不吃酸菜的小贱人 阅读(799)

京东淘宝day14

1.京淘项目前后端搭建策略2.京淘前台项目创建2.1创建项目2.1.1编辑项目名称2.1.2添加继承/依赖/插件<?xmlversion="1.0"encoding...

Riqk_Qin 阅读(701)