一、使用内部类的原因
内部类表示定义在另一个类中的类。使用内部类的原因主要有以下三点:
1、内部类的方法可以访问该类定义所在作用域内的数据,包括私有数据;
2、内部类可以使其自身对包中的其他类隐藏起来;
3、需要定义一个回调函数时,使用匿名内部类比较便捷。
二、内部类创建对象
1、内部类不是静态类,创建对象的方式为:
OuterClass out = new OuterClass();
InnerClass in = out.new InnerClass();
或是将上面两条语句合成下面一条:
InnerClass in = new OuterClass().new InnerClass();
public class Outer {
class Inner{
}
public static void main(String[] args) {
Outer out = new Outer();
Inner in = out.new Inner();
//也可以将上面两句合为下面的一句
Inner inn = new Outer().new Inner();
}
}
2、内部类是静态类,创建对象的方式是InnerClass in =new OuterClass.InnerClass();
也可以直接在外部类中使用下面的方式创建
InnerClass in =new InnerClass();
内部类中声明的所有静态域都必须是final,原因是我们希望一个静态域只有一个实例,不过对于每一个外部对象,会分别有一个单独的内部类实例,如果这个域不是final,它可能就不是唯一的。
public class Outer {
static class Inner{
}
public static void main(String[] args) {
Inner in = new Outer.Inner();
Inner in1 = new Inner();
}
}
三、内部类中属性和方法的调用
1、非静态内部类中的属性和方法调用
对于内部类中的属性和方法,无论是用private还是public修饰,在外部类Outer中都可以访问到。非静态内部类可以有静态属性,必须加上final,不然会报错;里面不能有静态方法。例如将下面非静态内部类的print前面加上static final会报错。调用方式:
内部类名.静态属性名
内部类对象.静态属性名(尽量用上面通过内部类名调用的方式)
内部类对象.普通属性名
内部类对象.普通方法名。
public class Outer {
class Inner{
private static final int i=6;
private String s = "non-static";
public static final String ss = "field";
private void print(){
System.out.println("non-static print");
}
}
public static void main(String[] args) {
Outer out = new Outer();
Inner in = out.new Inner();
//也可以将上面两句合为下面的一句
Inner inn = new Outer().new Inner();
System.out.println(inn.i);
System.out.println(Inner.i);
System.out.println(inn.s);
System.out.println(Inner.ss);
inn.print();
}
}
输出结果:
6
6
non-static
field
non-static print
2、静态内部类中的属性和方法调用
对于内部类中的属性和方法,无论是用private还是public修饰,在外部类Outer中都可以访问到。静态内部类可以有静态属性和方法,静态属性不加上final,也不会报错,编译运行都可以通过,但还是希望对于静态域都加上final。对于静态属性和方法也是可以通过内部类对象进行访问的,但是尽量用通过内部类名调用的方式,调用方式:
内部类名.静态属性名
内部类名.静态方法
内部类对象.普通属性名
内部类对象.普通方法名。
public class Outer {
static class Inner{
private final static int i=3;
public String s="good";
private static String ss = "job";
private static void print() {
System.out.println("InnerClass");
}
private void jump() {
System.out.println("jump");
}
}
public static void main(String[] args) {
System.out.println(Inner.i);
Inner.print();
Inner in = new Outer.Inner();
System.out.println(in.s);
System.out.println(in.ss);
in.jump();
}
}
输出结果:
3
InnerClass
good
job
jump
4、匿名内部类
如果只创建这个类的一个对象,就不必命名了,这种类被称为匿名内部类。
通常的语法格式是:
new TypeName(construction parameters){
inner class methods and data;
}
TypeName可以是接口,也可以是类名,如果是接口,则不能有任何构造参数。
new InterfaceName(){
methods and data;
对接口使用匿名内部类比较常见,在JDK8中出现了lambda表达式,现在用lambda表达式来实现以前用匿名内部类实现的一些功能,代码的书写会更加简洁。如创建一个线程:
public class MyThread {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("run1");
}
}).start();;
//使用lambda表达式创建新线程,书写更加简洁
new Thread(()-> System.out.println("run2")).start();;
}
}