内部类

写在前面:内部类在编译后,会产生类似Outer$Inner.class这样的字节码文件(Outer为外部类类名,Inner为内部类内名),

假如是局部内部类,字节码文件会是Outer$1Inner.class,Outer$2Inner.class这种格式

假如内部类是匿名形式,那么会产生Outer$1.class这样的字节码文件,第二个匿名类则是Outer$2.class。

这里我定义了两个成员内部类,类名都是Inner,并不冲突

然后如果你想看一下内部类内容,可以使用 javap -private 命令~~我就不贴出来了

 

所以的内部类都可以直接访问到外部类的成员变量,因为内部类中持有一个外部类的引用(静态成员内部类除外)

 

 

1. 成员内部类

package InnerClass;

/**
 * @author LiFeng
 * @create 2019-09-10 上午 11:19
 * @describe
 */
public class Outer {
	private String name = "out";
	private int sex = 1;

	/**
	 * 外部类Outer中定义了内部类Outer,但是并不持有Inner的实例对象
	 * 修饰符通常为private,私有化内部类,以阻止其他程序对其直接访问,想要访问必须通过外部类提供的接口
	 * 这里设为public为演示如何在其他类中访问内部类
	 */
	public class Inner {
		private String name = "Inner";
		private int age = 20;

		/**
		 * 成员内部类访问外部类的属性或方法时,若两者不存在同名情况,可直接访问
		 * 若存在同名,则采用以下方式 Outer.this.xxx()   或者   Outer.this.xx
		 */
		public void innerMethod() {
			name = "hello";
			sex = 2;
			age = 18; // 直接访问外部类不同名属性
			Outer.this.name = "outHello"; // 访问外部类同名属性
		}

		/**
		 * 如果想定义静态成员,则内部类必须是静态的
		 */
//		public static void test() {
//			System.out.println("hello world");
//		}
	}

	/**
	 * 外部类想要访问内部类成员属性,则必须先持有其实例对象
	 * 若内部类被static修饰(极少见,若内部类中定义了静态成员,则该内部类必须是静态)那么内部类只能访问外部类中的静态成员。
	 * 此时,外部类可以直接这样访问内部类的静态成员Inner.test()(仅限静态成员,极少这样做,就不写演示代码了)
	 */
	public void outerMethod() {
		new Inner().innerMethod();
	}

}

class Run {
	public static void main(String[] args) {
		Outer outer = new Outer();
		// 外部获取Inner实例对象的方式
		Outer.Inner inner = outer.new Inner();
		inner.innerMethod();
		//如果内部类是静态的,可以这样访问静态内部类的静态成员
//		Outer.Inner.test();

	}
}

 

2. 局部内部类

定义在外部类中的局部位置上。当内部类被定义在局部位置上,只能访问被final修饰的变量。(不常用,不过多介绍)

这里需要了解一下  为什么局部内部类和匿名内部类只能访问final修饰的变量?可以参考这篇文章,但是要注意的是,局部内部类不仅限于访问局部变量,成员变量也是可以访问的。

https://blog.csdn.net/sf_climber/article/details/78326984

 

3. 匿名内部类

匿名内部类(对象):没有名字的内部类,匿名内部类其实就是一个匿名子类对象。匿名内部类的格式:new 父类名 或者 接口名(){ 定义子类成员或者覆盖父类方法 }    其实它是一种特殊的局部内部类,所以它也有着局部内部类同样的访问限制问题。

package InnerClass;

/**
 * @author LiFeng
 * @create 2019-09-10 下午 2:10
 * @describe
 */
public class Outer3 {


	public void syso() {

		// 方式一:编译通过,可以执行
		new Thread() {
			void show() {
				System.out.println("show run");
			}
		}.show();


		// 方式二:编译不通过
		Object obj = new Object() {
			void show() {
				System.out.println("show run");
			}
		};
		// 此处编译不通过,提示找不到该方法,很显然匿名内部类对象被向上转型为了Object类,而Object中确实是不存在sho()方法的
//		obj.show();
	}

}

 

匿名内部类 new A(){ } 实际上产生的是一个A的子类的实例对象,我们可以通过看编译后的字节码文件证明。上例中第一个匿名内部类通过反编译后的代码。

package InnerClass;

import java.io.PrintStream;

final class Outer3$1
  extends Thread
{
  void show()
  {
    System.out.println("show run");
  }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值