java内部类

内部类

概念

在这里插入图片描述
所谓内部类就是在一个类的内部再申明一个类。

凡是申明在类的成员位置的就是成员内部类,凡是申明在方法或者代码块中的类都是局部内部类。

成员内部类

非静态成员内部类

基本写法

案例:

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午9:16:28
 */
public class Outer {
	private String name;
	public void method() {
		System.out.println("这是外部类的非静态成员方法");
	};
	public static void stMethod() {
		System.out.println("外部内的静态成员方法");
	}
	
	//非静态成员内部类
	public class Inner{
		private int age;
		public void innerMethod() {
			System.out.println("内部类的非静态成员方法");
		}
		//非静态内部类中不能申明静态方法
//		public static void innerStMethod() {
//			System.out.println();
//		}
	}
}

非静态成员内部类的对象创建。

如果要创建内部类的对象,则必须先有外部类对象。

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午9:21:29
 */
public class Test {
	public static void main(String[] args) {
		//首先创建外部内对象
		Outer outer = new Outer();
		//使用外部内对象创建内部类对象
		Outer.Inner inner = outer.new Inner();
		//使用匿名对象
		Inner inner1 = new Outer().new Inner();
		inner.innerMethod();
	}
}

tips:

在非静态内部类中不能申明静态方法。
在非静态的内部类中不能申明静态的成员变量,但是可以申明常量。

内部类的一些特征

编译:所有的成员内部类都会被编译成一个独立的字节码文件,文件的名称为“外部类的类名$内部类类名.class”。
在这里插入图片描述
访问权限问题

成员的内部类可以使用任何访问修饰符,表现的状态和其他成员一样。

在内部类中可以访问外部类的所有成员
在非静态成员内部类中可以调用所有的外部类方法
在非静态成员内部类中使用外部类的this的时候,语法是:外部类类名.this。
在这里插入图片描述

静态成员内部类

案例:

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午9:39:34
 */
public class Outter {
	//静态成员内部类
	public static class Inner{
		private String name;
		public void method() {
			System.out.println("内部类的非静态方法");
		}
		public static void stMethod() {
			System.out.println("内部类的静态方法");
		}
	}
}
/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午9:40:56
 */
public class Test {
	public static void main(String[] args) {
		//创建静态内部类对象不需要外部类对象
		Outter.Inner inner = new Outter.Inner();
		inner.method();
		//直接调用静态成员内部类的静态方法
		Outter.Inner.stMethod();
	}
}

静态内部类中可以申明静态和非静态的方法和成员变量。

静态内部类中可以调用外部类的任何静态的成员变量和方法,但是不能调用任何非静态的方法和变量,更不能使用外部类的this对象。
在这里插入图片描述

局部内部类

申明在类的代码块中的类就是局部内部类。

案例:

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:03:28
 */
public class Outter {
	
	public void method() {
		System.out.println("外部类的成员方法");
		class Inner{
			private String name;
			public void method() {
				System.out.println("局部内部类的方法");
			}
		}
		//局部内部类的使用访问就是这个方法
		Inner inner = new Inner();
		inner.method();
	}
	public static void main(String[] args) {
		Outter outer = new Outter();
		outer.method();
	}
}

局部内部类的使用范围就是局部范围,就是申明的范围内。
局部内部类无法使用任何访问修饰符修饰,也不能修饰为static

局部内部类访问外部类中的成员或者局部变量。

在局部内部类中可以访问外部了的任何成员。可以使用外部类的this对象等等。
在局部内部类中如果要使用外部类的局部变量,如果jdk是1.7之前,则局部变量必须是final修饰的,1.7之后就不需要了,其实就是默认就是final。

在这里插入图片描述
局部内部类在方法执行结束之后,内对象依然存在的情况:

public class A {
	public void show() {
		
	}
}
/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:19:08
 */
public class Outter {
	public A getA() {
		int x = 10;
		class B extends A{
			public void show() {
				System.out.println(x);
			}
		}
		B b = new B();
		return b;
	}
	
	public static void main(String[] args) {
		A a = new Outter().getA();
		System.out.println(a);
		a.show();
	}
}	

局部内部类的编译情况:

源代码:

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:25:00
 */
public class Outter {
	public void methoda() {
		class Inner{}
	}
	public void methodb() {
		class Inner{}
	}
}

编译后的情况:
在这里插入图片描述
局部内部类编译后的类名是:外部类类名$index内部类类名.class 。 这里的index是编译器根据方法的编译前后顺序给的索引。

抽象内部类和内部接口

[1]内部类能不能申明为抽象类?

成员非静态内部类可以是抽象类,但是只能被内部类继承
在这里插入图片描述
[2]成员静态内部类可以被申明为抽象类.

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:34:10
 */
public class Outter {
	public abstract static class Inner{
	}
	//继承内部抽象类
	class B extends Inner{
	}
}
//外部的其他类可以继承抽象静态内部类
class A extends Outter.Inner{
}

[3]局部内部类,局部内部类可以申明为抽象的。

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:34:10
 */
public class Outter {
	
	public void method() {
		abstract class Inner{
			
		}
		//继承局部的抽象内部类
		class A extends Inner{
			
		}
	}
}

[4]接口内部申明内部接口

接口中可以申明:内部接口,成员内部类,局部内部类。

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:42:06
 */
public interface IOutter {
	//内部接口
	public interface IInner{
		
	}
	//内部类
	public class AInner {
		
	}
	//静态成员内部类
	public static class SAInner{
		
	}
	default void method() {
		//局部内部类
		class Inner{
			
		}
	}
}

测试:

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午10:47:37
 */
public class Test {
	public static void main(String[] args) {
		//创建接口中的非静态成员内部类对象
		IOutter outter = new St();
		IOutter.AInner ainner = new AInner();
		//创建接口的静态成员内部类对象
		IOutter.SAInner sainner = new SAInner();
		//创建内部接口对象
		IOutter.IInner iinner = new Geek();
	}
}
//实现外部接口
class St implements IOutter{
}
//实现内部接口
class Geek implements IOutter.IInner{
}

接口中的静态方法:jdk8的新特性

匿名内部类

所谓匿名内部类就和匿名对象一样,没有名字。

常用来直接继承抽象类,或者实现接口。

匿名内部类只能使用一次,不能使用第二次。

案例:使用匿名内部类实现一个线程。

/**
 * @author 戴着假发的程序员
 * @TODO 匿名内部类
 * @organization 飞虎队 2020年8月31日 上午11:07:06
 */
public class Main {
	public static void main(String[] args) {
		new Main().mt();
	}

	public void mt() {
		// 开启一个线程 线程类:继承Thread,实现Runnable接口
		// 使用匿名内部类继承Thread类
		new Thread() {
			public void run() {
				System.out.println("匿名内部类继承Thread类实现一个线程类");
				method();
			}

			public void method() {
				System.out.println("匿名内部类自定义的方法");
			}
		}.start();
		// 使用匿名内部类实现Runnable接口
		new Thread(new Runnable() {
			private String name = "runnable";

			public void run() {
				System.out.println("匿名内部类实现Runnable接口实现一个线程类");
				System.out.println(name);
				m();//调用外部类的其他成员
			}
		}).start();
	}

	public void m() {
		System.out.println("外部类的成员方法");
	}
}

匿名内部类就是使用{}来实现或者继承某一个类。

常见的方式:

类名/接口  对象名 = new 类名/接口(){实现接口或者继承父类的重写的方法}
		//匿名内部类继承Thread
		Thread ta = new Thread() {
			public void run() {
				System.out.println("一个线程");
			} 
		};
		ta.start();

使用场景:

当一个接口或者一个父类申明的抽象方法非常有限,而我们只需要这个类对象一次,这时就使用匿名内部类创建对象。

		// 使用匿名内部类实现Runnable接口
		new Thread(new Runnable() {
			private String name = "runnable";
			public void run() {
				System.out.println("匿名内部类实现Runnable接口实现一个线程类");
				System.out.println(name);
				m();//调用外部类的其他成员
			}
		}).start();

匿名内部类中同样可以使用外部类的任何成员。

匿名内部类谈不上任何修饰符。

匿名内部类的编译:

匿名内部类也会被独立的编译成一个字节码文件,命名为 ”外部类类名$index.class”。 index就是编译器给所有的内部类给的索引。
在这里插入图片描述

静态内部类的单利中的使用

/**
 * @author 戴着假发的程序员
 * @TODO 
 * @organization 飞虎队
 * 2020年8月31日 上午11:25:50
 */
public class Singleton {
	//申明静态的私有的当前类对象成员
//	private static Singleton instance;
	//使用静态内部类实例化对象
	private static class Inner{
		//在类加载的创建
		private static Singleton instance = new Singleton();
	}
	//构造方法私有化
	private Singleton() {
	}
	//静态public的获取当前类对象的方法
	public static Singleton getInstance() {
		//加载内部类
		return Inner.instance;
	}
	
	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}
}
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

戴着假发的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值