1、结构允许嵌套,在一个类的内部定义其他的类,这样的类就称为内部类。
2、内部类本身是一个独立且完善的类结构,在一个类的内部除了属性和方法外还可以定义class类。
class Outer { //外部类
private String msg = "一只瓶子a" ; //私有成员属性
public void fun() { //普通方法
Inner in = new Inner() ; // 实例化内部类对象
in.print() ; //调用内部类方法
}
class Inner { // 在Outer类的内部定义的Inner类
public void print() {
System.out.println(Outer.this.msg) ; //调用Outer类中的属性
}
}
}
public class JavaDemo {
public static void main(String args []) {
Outer out = new Outer() ;
out.fun() ;
}
}
内部类的优势:内部类可以轻松访问其外部类的私有属性,外部类也可以轻松访问内部类的私有属性和方法。
如果不使用内部类,msg要被外部访问需要提供有getter方法。
class Outer {
private String msg = "一只瓶子a" ; //私有成员属性
public void fun() { //普通方法
// 需要将当前对象Outer类传递到Inner类中
Inner in = new Inner(this) ;
in.print() ;
}
}
class Inner {
private Outer out ;
// 通过构造方法获取Outer类对象
public Inner(Outer out) {
this.out = out
}
public void print() {
System.out.println(this.out.getMsg()) ; //访问Outer类中的私有属性
}
}
public class JavaDemo {
public static void main(String args []) {
Outer out = new Outer() ;
out.fun() ;
}
}
3、外部可以产生内部类的实例化对象:外部类.内部类 内部类对象 = new 外部类().new 内部类() ;
上述程序在内部类编译完成之后自动形成了一个“Outer$Inner.class”类文件,其中“$”符号在程序中即为“.”,所以内部类全称即为“外部类.内部类”,内部类实例化对象时一定要先保证外部类已经实例化。
如果内部类仅希望其外部类使用,那么给该内部类定义private访问权限即可。
4、抽象类和接口中都可以定义内部结构。
定义一个接口,利用内部类实现该接口,从JDK1.8之后,接口中追加了static方法可以不受到实例化对象的控制。
interface IChannel {
public void send() ;
class ChannelImpl implements IChannel {
public void send() {
System.out.println("一只瓶子a")
}
}
public static IChannel getInstance() {
return new ChannelImpl() ;
}
}
内部类是一种非常灵活的定义。
5、static定义内部类(需要注意的是,static定义的不管是类还是方法都只能访问static成员)
在内部类上使用static定义,那么这个内部类就成了“外部类”。此时实例化内部类:外部类.内部类 内部类对象 = new 外部类.内部类() ;
6、static定义内部接口(常用)
实现内部接口时使用-外部接口.内部接口
使用static定义内部接口,是因为这些操作属于一组相关定义。
7、方法中定义内部类
在方法内部提供内部类的定义,该内部类可以直接访问外部类中的私有属性也可以直接访问方法中的参数,但是对于方法中参数的直接访问是从JDK1.8开始支持的。在JDK1.8之前,如果方法中定义的内部类想要访问方法中的参数,则参数前必须使用final关键字。这一优化处理主要是为了其扩展的函数式编程功能。
8、匿名内部类
匿名内部类是一种简化的内部类的处理形式,其主要是在抽象类和接口的子类上使用的。
interface IChannel {
public void send(String str) ;
}
public class JavaDemo {
public static void main(String args []) {
IChannel ic = new IChannel() { //接口 IChannel不能直接实例化,所以此处需要匿名内部类,匿名内部类避免了定义只会使用唯一一次的实现子类。
public void send(String str) {
System.out.println(str) ;
}
};
ic.send("一只瓶子a");
}
}
在接口中利用匿名内部类实例化
interface IChannel {
public void send(String str) ;
public static IChannel getInstance() {
// 接口中定义的匿名内部类——实现接口中的抽象方法
return new IChannel() {
public void send(String str) {
System.out.println(str)
}
}
}
}
public class JavaDemo {
public static void main(String args []) {
IChannel.getInstance().send("一只瓶子a") ;
}
}