一、内部类的定义与使用
在类的内部进行其他结构类结构嵌套操作
二、内部类的优缺点
优点:
- 内部类与外部类可以方便的访问彼此的私有域(包含私有方法、私有属性)
class Outter {
private String msg = "Outter";
//内部类
class Inner {
private String inmsg = "Inner";
public void fun(){
//直接调用外部类的私有属性
System.out.println(msg);
}
}
public void test(){
Inner in = new Inner();
in.fun();
}
}
class Check {
public static void main(String[] args) {
Outter out = new Outter();
out.test();
}
}
以上是在Outter类中定义了一个Inner的内部类,在Inner内部类中要想访问外部类的私用属性msg时,可以直接调用。但要是想在一个类中使用另一个类中的私有属性且不是内部类的时候,就有点复杂了。如下的代码也是想要在Inner类中使用Outter类中的私有属性,这里就需要构造注入来实现。可以看出内部类可以很方便的访问外部类的私有属性。
class Outter {
private String msg = "Outter";
public String getMsg(){
return this.msg;
}
public void test(){
Inner in = new Inner(this);//this表示当前对象out
in.fun();
}
}
class Inner {
private String inmsg = "Inner";
private Outter out;
//构造注入
public Inner(Outter out) {
this.out = out;
}
public void fun(){
System.out.println(out.getMsg());
}
}
class Check {
public static void main(String[] args) {
Outter out = new Outter();
out.test();
}
}
- 内部类是另外一种封装(保护性),对外部的其他类隐藏。
相当于现实生活中人的心脏包在身体内部。 - 内部类可以实现Java单继承的局限
class A {
private String msg = "test";
public String getMsg(){
return msg;
}
}
class B {
private int age = 20;
public int getAge(){
return age;
}
}
class C {
class InnerClassA extends A {
public String name() {
return super.getMsg();
}
}
class InnerClassB extends B {
public int age() {
return super.getAge();
}
}
public String name() {
return new InnerClassA().name();
}
public int age() {
return new InnerClassB().age();
}
}
class Check {
public static void main(String[] args) {
C c = new C();
System.out.println(c.name());
System.out.println(c.age());
}
}
当C类想要同时继承A、B类的时候,可以先让C继承B,然后B再继承A来实现。当有了内部类的时候,就可以通过内部类来实现多继承,在C类中使用多个内部类分别继承A、B类,这样C类中就可以使用A、B类中的私有属性,从而实现多继承。
内部类的缺点就是结构复杂。
三、内部类与外部类的关系
- 对于非静态内部类,内部类的创建需要依赖外部类对象,在没有外部类实例之前无法创建非静态内部类
- 内部类是一个相对独立的个体,与外部类没有is-a关系
- 内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类元素,需要通过内部类的引用间接访问
//内部类直接访问外部类的元素
class Outter {
private String msg;
private int age;
class Inner {
public void display(){
msg = "test";
age = 20;
System.out.println(msg);
System.out.println(age);
}
}
public void test() {
Inner in = new Inner();
in.display();
}
}
class Check {
public static void main(String[] args) {
Outter out = new Outter();
out.test();
}
}
class Outter {
class Inner {
private String msg = "Inner";
}
public void test() {
Inner in = new Inner();
System.out.println(in.msg);//外部类通过引用访问内部类元素
}
}
class Check {
public static void main(String[] args) {
Outter out = new Outter();
out.test();
}
}
四、创建内部类语法(在外部类的外部)
- 创建非静态内部类
外部类.内部类 内部类引用 = new 外部类( ).new 内部类( );
Outter.Inner in = new Outter( ).new Inner( ); - 创建静态内部类
外部类.内部类 内部类引用 = new 外部类.内部类( );
Outter.Inner in = new Outter.Inner( );
五、内部类的分类
- 成员内部类
a. 成员内部类不能存在任何static变量或方法,可以访问外部类的静态域
b. 成员内部类是依附外部类的,所以只有先创建了外部类才能创建内部类。
class Outter {
private String name = "test";
private static int age = 20;
class Inner {
public void fun() {
System.out.println(name);//访问外部类的私有属性
System.out.println(age);//访问外部类的静态属性
}
}
}
class Check {
public static void main(String[] args) {
Outter.Inner in = new Outter().new Inner();//主方法中创建内部类
in.fun();
}
}
- 静态内部类
a. 静态内部类的创建不需要依赖外部类,可以直接创建
b. 静态内部类不可以使用任何外部类的非static域(包含属性与方法),但是可以存在自己的成员变量
class Outter {
private String name = "test";
private static int age = 20;
static class Inner {
private String name;//静态内部类的私有属性
public void fun() {
System.out.println(age);//访问外部类的静态属性
}
}
}
class Check {
public static void main(String[] args) {
Outter.Inner in = new Outter.Inner();
in.fun();
}
}
- 方法内部类
a. 方法内部类不允许使用访问权限修饰符 public、private、protected均不允许
b. 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问他以外,其他地方均不能访问。
c. 方法内部类如果想要使用方法形参,该形参必须使用final声明(JDk8将形参变为隐式final声明)
class Outter {
private int num = 5;
//隐式final声明
public void display(int temp) {
//方法内部类
class Inner {
public void fun() {
System.out.println(num);
System.out.println(temp);
}
}
Inner in = new Inner();
in.fun();
}
}
class Check {
public static void main(String[] args) {
Outter out = new Outter();
out.display(20);
}
}
- 匿名内部类
匿名内部类就是一个没有名字的方法内部类。因此特点与方法内部类完全一样,除此之外还有两个自己的特点:
a. 匿名内部类必须继承一个抽象类或者实现一个接口
b. 匿名内部类没有构造方法,因为他没有类名
//接口
interface MyInterface {
void test();
}
class Outter {
private int num = 5;
public void display(int temp) {
//匿名内部类
new MyInterface() {
@Override
public void test() {
System.out.println("匿名实现MyInterface接口");
System.out.println(temp);
}
}.test();
}
}
class Check {
public static void main(String[] args) {
Outter out = new Outter();
out.display(20);
}
}
成员内部类 VS 静态内部类
静态内部类不能访问外部的成员变量,但可以拥有自己的成员变量;
成员内部类不能拥有静态变量,但可以访问外部静态变量。