您的位置 首页 java

直切主题,把最核心的给你,超详细深入浅出Java内部类

什么是内部类:

一个类内部除了有属性和方法,还可以有其他类,内部类也可以在方法或代码块中。 (往下会代码示例)

可以简单的理解为 花括号里 { } 里面再定义一个类,那么这个类就称为:内部类。 因为理论上内部类可以在类任意位置,所以代码块也好,普通方法也可以。

内部类的作用:

1.增强封装,把内部类放在外部类当中,不允许其它类访问这个内部类。

2.增加了代码一个维护性,不涉及到其他类。

3.内部类可以直接访问外部类当中的成员。

内部类分为四种:

  • 实例内部类:直接定义在类当中的一个类,在类前面没有任何一个修饰符。
  • 静态内部类:在内部类前面加上一个 static
  • 局部内部类:定义在方法当中的内部类。
  • 匿名内部类:属于局部的一种特殊情况。

实例内部类

 //外部类
//外部类
 class Outer {
 String str = "一颗剽悍的种子";
//内部类
class Inner{
void fun() {
System.out.println(str);
}
}
}
public class Test2{
public static void main(String[] args) {
Outer out = new Outer();
//实例内部类
out.new  Inner ().fun();
}
}  

运行结果:

上面代码示例有个细节:就是我们提到过的内部类的作用, 内部类可以访问外部类的成员。

实例化 内部类的格式:

代码本身很简单,只要理解类的语法和对象实例化方式就可以了,了解它的底层才有趣, 创建内部类的时候发生了什么? 在创建内部类的时候,会有一个外部类的引用。

我们可以用代码编译后的 class文件 通过我们的 反编译 工具来看。

 class Outer$Inner
{
final Outer this$0;
void fun()
{
System.out.println(str);
}
Outer$Inner()
{
this$0 = Outer.this;
super();
}
}  

从上面的代码可以看到,内部类当中除了有自己的引用,还有外部类的引用。在堆中相当于外部类有一个地址,内部类有两个地址,一个是自己内部类的,一个是指向外部类的地址。

静态内部类

有接触过 Java 静态这个知识点的小伙伴应该都知道,谈到静态无非就是对static关键字的理解和运用,这么说你可能会好懂一些。

说得更直接点就是内部类前面加上一个 static 就是静态内部类。

 //外部类
 class Outer {
static String str = "一颗剽悍的种子";
//静态内部类
static class Inner{
void fun() {
System.out.println(str);
}
}
}
public class Test2{
public static void main(String[] args) {
new Outer.Inner().fun();;
}
}  

运行结果

注意点:可以看到上面成员也是用static声明静态,是因为声明static无法直接调用非 static变量 或方法。

为什么?

我们都知道static是最先执行,在加载字节码就会自动调用,而且在主方法main之前,比构造方法早,此时非static属性和方法还没有完成初始化呢。

还有与上面非 static 定义内部类有两点不同:

1.静态内部类的创建格式不需要实例化,具体格式如下:

new 外部类(). 内部类 ();

2.静态内部类当中没有外部类的引用。

为什么?

因为加上static 静态内部类是属于外部类的,上面所说也可以看出它没有用new 而是通过 .类的方式。

还是通过我们的反编译查看class文件,有码有真相。

 static class Outer$Inner
{
void fun()
{
System.out.println(Outer.str);
}
Outer$Inner()
{
}
}  

局部内部类

开头说什么是内部类当中,有说到内部类不仅可以定义在外部类当中,也可以定义在方法当中,而定义在方法当中的类称为局部内部类

 //外部类
class Outer {
void fun_1() {
String  name = "一颗剽悍的种子";
 class Inner{
void fun_2() {
System.out.print(name);
}
}
 Inner in = new Inner();
 in.fun_2();
}
}
public class Test2{
public static void main(String[] args) {
new Outer().fun_1();
}
}  

运行结果

局部内部类有什么局限性呢?

1.局部内部类只能在定义方法中使用。 可以看到代码示例,在方法中创建内部类并且调用内部类里的方法,后续实例化只要调用外部类里的 fun_1 方法就可以。

2.不能使用 public、protected、private 修饰 。 这一条是对应第一条的,你想想,你已经在方法中创建了,只在方法中使用,你还用这些权限干嘛 ???

3.局部类当中不能使用static变量。 上面静态内部类时说过,static是属于外部类的,所以在方法里的内部类定义static变量会报错。

除了局部内部类的局限性,还可以看到在代码实例中,内部类是可以直接使用方法中的变量的。

(在jdk1.7之前内部类想访问方法中的变量是需要加上final的,我们知道final是用来声明常量的,fianl需要设置好值而且不能修改。)

jdk1.8版本之后不需要,正好我的jdk1.8 所以就不用加final了,但是真实情况下,通过反编译工具看class文件会发现编译时已经帮我们自动加上了。

(你会发现随着语言的发展,让你更易于开发的同时,你离本质也更加的遥远)

 class Outer$1Inner
{
final Outer this$0;
private final String val$name;
void fun_2()
{
System.out.print(val$name);
}
Outer$1Inner()
{
this$0 = final_outer;
val$name = String.this;
super();
}
}  

到这里可能有小伙伴会问,为啥内部声明变量需要加上final,这里就不展开了,因为涉及到 final 在方法区以及代码运行后的堆栈关系,下次有机会再写一篇。

匿名内部类

根据字面意思就知道没有命名的内部类,那么匿名内部类就是没有 构造器 的,因为我们都知道类的构造器需要跟类同样的命名。

new 父类 或 接口

上面围绕四种内部类展开,实例内部类,静态内部类、局部内部类、匿名内部类,因为匿名内部类的应用是比较少,所以简单的谈谈就没有代码示例,等有用到,而且好的例子,可以再单独写一篇滴。

作者:CSDN博主「一颗剽悍的种子」

原文链接:

文章来源:智云一二三科技

文章标题:直切主题,把最核心的给你,超详细深入浅出Java内部类

文章地址:https://www.zhihuclub.com/200163.shtml

关于作者: 智云科技

热门文章

网站地图