内部类的基本概念
内部类:所谓内部类就是在一个类的内部进行其他类结构的嵌套的操作
eg:观察内部类的定义:
class Outer {
private String msg = "Hello World";
//--------------------------------
class Inner {//定义一个内部类
public void print() {//定义一个普通方法
System.out.println(msg);//调用Outer类中的msg属性
}
}
//-----------------------------------
public void fun() {//在Outer类中定义一个普通方法
Inner in = new Inner();//产生一个内部类对象
in.print();//调用内部类中的print方法
}
}
public class Test_10_22 {
public static void main(String[] args) {
Outer out = new Outer();//产生Outer类对象
out.fun();//调用Outer类中的fun方法
}
}
通过以上代码我们会发现,引入内部类后,程序的结构有些混乱。虽然内部类破坏了程序的结构,但是从另一方面 来讲,内部类可以方便的操作外部类的私有访问。
内部类的优点
- 内部类与外部类可以方便访问彼此的私有域(包含私有方法、私有属性)
- 内部类是另外一种封装(保护性),对外部的其他类隐藏(心脏包在人身体内部)
- 内部类可以实现Java单继承的局限
- 当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现
eg:使用内部类来实现多继承
class A {
private String name = "LZH";//A类的私有属性
public String getName() {
return this.name;
}
}
class B {
private int age = 18;//B类的私有属性
public int getAge() {
return this.age;
}
}
class Outer {
class InnerClassA extends A {//Outer类内部的InnerClassA类继承了A类
public void print() {
System.out.println(getName());
}
}
class InnerClassB extends B {//Outer类内部的InnerClassB类继承了B类
public void print() {
System.out.println(getAge());
}
}
}
public class Test_10_22 {
public static void main(String[] args) {
Outer.InnerClassA in1 = new Outer().new InnerClassA();//产生内部类InnerClassA的对象
Outer.InnerClassB in2 = new Outer().new InnerClassB();//产生内部类InnerClassB的对象
in1.print();//调用InnerClassA类的print方法
in2.print();//调用InnerClassB类的print方法
}
}
内部类的缺点
结构太复杂
内部类与外部类的关系
- 对于非静态内部类,内部类的创建需要依赖外部类对象,在没有外部类实例之前无法创建非静态内部类。
- 内部类是一个相对独立的个体,与外部类没有is-a关系
- 内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类元素,需要通过内部类的引用间接访问
eg:外部类可以通过内部类引用间接访问内部类元素
class Outer {
public void print() {//通过内部类引用来访问内部类元素
Inner in = new Inner();
in.print();
}
class Inner {
public void print() {
System.out.println("Hello World");
}
}
}
public class Test_10_22 {
public static void main(String[] args) {
Outer out = new Outer();
out.print();
}
}
创建内部类语法(在外部类外部)
- 创建非静态内部类
外部类.内部类 内部类引用 = new 外部类().new 内部类();
eg: Outter.Inner in = new Outter().new Inner();
- 创建静态内部类
外部类.内部类 内部类引用 = new 外部类.内部类();
eg: Outter.Inner in = new Outter.Inner();
内部类的分类(存在私有内部类、静态、成员均可)
- 成员内部类
- 静态内部类
- 方法内部类
- 匿名内部类
成员内部类(成员方法)
- 成员内部类内部不能存在任何static变量或方法,可以访问外部类的静态域
- 成员内部类是依附外部类的,所以只有先创建了外部类才能创建内部类
静态内部类(静态方法)
- 静态内部类的创建不需要依赖外部类,可以直接创建
- 静态内部类不可以使用任何外部类的非static域(包含属性与方法),但可以存在自己的成员变量
eg:使用static创建静态内部类
class Outer {
private static String msg = "Hello World";
static class Inner {//定义一个静态内部类
public void print() {//此时只能使用外部类中的static操作
System.out.println(msg);//调用msg属性
}
}
public void fun() {
Inner in = new Inner();//产生内部类对象
in.print();//调用内部类中的print方法
}
}
public class Test_10_22 {
public static void main(String[] args) {
Outer out = new Outer();
out.fun();
}
}
方法内部类
- 方法内部类不允许使用访问权限修饰符 public private protected均不允许
- 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它之外,其他地方均不能访问。
- 方法内部类如果要想使用方法形参,该形参必须使用final声明(JDK8将形参变为隐式final声明)
eg:使用方法内部类
class Outer {
private int num;
public void print(int test) {//定义一个普通方法
class Inner {//定义一个方法内部类,只能通过此方法访问
public void fun() {
num++;//直接访问Outer中的私有属性
System.out.println(num);
System.out.println(test);
}
}
Inner in = new Inner();//产生方法内部类对象
in.fun();//调用内部类中的fun方法
}
}
public class Test_10_22 {
public static void main(String[] args) {
Outer out = new Outer();
out.print(18);
}
}
匿名内部类
匿名内部类就是一个没有名字的方法内部类。因此特点与方法内部类完全一样,除此之外,还有两个自己的特点:
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类没有构造方法,因为它没有类名。
eg:使用匿名内部类
interface MyInterface {
void test();
}
class Outter {
private int num;
public void display(int para) { // 匿名内部类,实现了MyInterface接口
new MyInterface(){
@Override
public void test() {
System.out.println("匿名内部类"+para);
}
}.test();
}
}
public class Test {
public static void main(String[] args) {
Outter outter = new Outter();
outter.display(20);
}
}
总结
内部类的使用暂时不作为设计的首选。
内部类的特点如下:
- 破坏了程序的结构
- 方便进行私有属性的访问。(外部类也可以访问内部类的私有域)
- 如果发现类名称上出现了".",应当立即想到内部类的概念。