java基础之内部类
内部类或嵌套类
在一个类的内部定义另一类(接口、枚举或注解)
格式:
public class OuterClass {
//成员变量和方法
class InnerClass{//一个内部类的定义
//成员变量和方法
}
}
优点:对只在一处使用的类进行分组;提高封装性;增强代码的可读性
内部类分类:
成员内部类
局部内部类
匿名内部类
静态内部类
按内部类是否被static修饰,分为静态的和非静态的
成员内部类
- 是定义在外层类的类体中且没有用static修饰。
- 说明
1)在成员内部类中可以定义自己的成员变量和方法,也可以定义自己的构造方法。
2)访问修饰符可是private、public、protected或缺省。
3)成员内部类中不能定义static变量和static方法。
public class OuterClass {
private int x = 200;
class InnerClass{
int y = 300;
public int calculate(){
return x + y;
}
}
public void makeInner(){
InnerClass ic = new InnerClass();
System.out.println(ic.calculate());
}
public static void main(String[] args){
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner=outer.new InnerClass();
System.out.println(inner.calculate());
}
}
运行结果是500
注意:
成员内部类中不能定义static变量和static方法。
成员内部类可以使用final和abstract修饰,含义与其他类一样
成员内部类还可以使用private、public、protected或包可访问修饰符
局部内部类
- 局部内部类是在方法体或语句块内定义类。
- 在方法体或语句块 (包括方法、构造方法、局部块、初始化块或静态初始化块) 内部定义的类称为局部内部类(local inner class)。
- 只在定义它的块内有效,同局部变量一样,在定义它的块之外不能访问,因此也不能有任何访问修饰符。
public class OuterClass2 {
public String x = "hello";
public void makeInner(int param){
final String y = "local variable";
class InnerClass{
public void seeOuter(){
System.out.println("x = " + x);
System.out.println("y = " + y);
System.out.println("param = " + param);
}
}
new InnerClass().seeOuter();
}
public static void main(String[] args){
OuterClass2 oc = new OuterClass2();
oc.makeInner(47);
}
}
注意:
- 局部内部类同方法局部变量一样,不能使用private、protected和public等访问修饰符修饰,也不能使用static修饰,但可以使用final或abstract修饰
- 局部内部类可以访问外层类的成员,若要访问其所在的参数和局部变量,这些参数和局部变量不能修改
- static方法中,定义的局部内部类,可以访问外层定义的static成员,不能访问外层的实例成员。
匿名内部类
- 将类的定义和实例的创建在一起完成,或者说在定义类的同时就创建一个实例。以这种方式定义的没有名字的类称为匿名内部类(anonymous inner class)。
一般格式如下:
new TypeName(){
/* 此处为类体 */
}
注:匿名内部类继承类或实现接口,不需要使用extends或implement关键字。不能同时实现继承类和实现接口。内部类体中,不能定义构造方法。
赋给引用变量:
TypeName obj = new TypeName(){
/* 此处为类体 */
};
定义类的同时用new关键字创建类的实例;即定义和创建对象在同一个位置
直接传递给方法:
someMethod(new TypeName() {
/* 此处为类体 */
}
);
构建对象作为方法调用的参数
【例】匿名内部类继承Animal类,覆盖eat()方法,同时创建匿名类的实例,并用dog指向它
class Animal{
public void eat(){
System.out.println("I like eat anything.");
}
}
public class AnimalTest {
public static void main(String[] args){
Animal dog = new Animal(){
@Override
public void eat(){
System.out.println("I like eat bones.");
}
};
dog.eat();
}
}
输出:I like eat bones.
【例】接口Printable声明print抽象方法,在主函数中声明一个接口变量,并创建实现接口的对象
interface Printable{
public abstract void print(String message);
}
public class PrintableTest {
public static void main(String[] args){
Printable printer = new Printable(){
@Override
public void print(String message){
System.out.println(message);
}
};
printer.print("这是wave");
}
}
匿名内部类一个重要的应用是编写JavaFX图形界面的事件处理程序
例:为button注册事件处理器
button.setOnAction(new EventHandler<ActionEvent>(){
@Override
public void handle(ActionEvent event){
label.setText(“你点击了确定按钮”);
}
});
静态内部类
静态内部类定义在外层类中,使用static修饰,静态内部类也称嵌套类(nested class)。
一般格式如下:
public class OuterClass {
//成员变量和方法
static class InnerClass{
//成员变量和方法
}
}
- 静态内部类中可以定义静态成员;
- 静态内部类只能访问外层类的静态成员;
- 创建静态内部类的实例不需要先创建一个外层类的实例。
【例】静态内部类实际是一种外部类
public class MyOuter {
private static int x = 100;
public static class MyInner{
private String y = "hello";
public void innerMethod(){
System.out.println("x = " + x);
System.out.println("y = " + y);
}
}
public static void main(String[] args){
MyOuter.MyInner snc = new MyOuter.MyInner();
snc.innerMethod();
}
}
public class MyOuter2 {
String s1 = "Hello";
static String s2 = "World";
interface MyInterface{
void show();
}
static class MyInner2 implements MyInterface{
@Override
public void show() {
System.out.println("s1 = " + new MyOuter2().s1);
System.out.println("s1 = " + s2);
}
}
public static void main(String[] args){
MyOuter2.MyInner2 inner2 = new MyOuter2.MyInner2();
inner2.show();
}
}