内部类
在一个类中定义另外一个类,这个类就做内部类或内置类(inner class),也称嵌套类,包含内部类的类称为外部类(outer class)。
- 成员类
如下例中,声明OuterOne外部类包含内部类InnerOne。其中外部类和内部类的其他成员处于同级位置,所以称为成员类。
public class OuterOne {
private int x =3;
InnerOne ino = new InnerOne(); //外部类有一个属性指向创建的内部类的对象
public class InnerOne{ //内部类
private int y =5;
public void innerMethod(){
System.out.println("y is "+y);
}
public void innerMethod2(){
System.out.println("z is "+x); //访问外部类变量
}
} //内部类变量
public void OuterMethod(){
System.out.println("x is "+x);
ino.innerMethod();
ino.innerMethod2();
}
public static void main(String[] args) {
Learning my = new Learning();
my.OuterMethod();
}
}
运行结果:
注意:
(1)内部类的命名除了不能与自己的外部类同名外,不必担心与其他类名冲突,因为其真实名字上了外部类名作为前缀。如,内部类InnerOne经过编译后出现OuterOne$InnerOne.class。
(2)在外部类中访问内部类一般通过在外部类的成员定义中创建内部类对象,例如:InnerOne ino = new InnerOne()。
(3)在内部类使用this,this指内部类的对象,要访问外部类的当前对象须加上外部类名作前提。例如:上例,可用OuterOne.this代表外部类的this对象。
- 静态内部类
定义为static的内部类称为静态类。静态类自动转化为顶层类,即没有父类,而且不能引用外部类成员或其他内部类成员。且只有静态内部类才能声明静态成员。
public class StaticEg {
public static class Person{ //声明一个静态的、公用的内部类。
private int age;
private String name;
static int count = 0; //声明一个静态变量
Person(String n,int a){
name = n;
age = a;
count++;
}
public void display(){
System.out.println("count=" +count +"\t\t" +name +"\t\t" + age);
}
}
public static void main(String[] args) {
StaticEg.Person p1 = new StaticEg.Person("小易", 14);
p1.display();
StaticEg.Person p2 = new StaticEg.Person("千千", 15);
p2.display();
StaticEg.Person p3 = new StaticEg.Person("小舞", 16);
p3.display();
}
}
运行结果:
- 局部内部类:
Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。
public class PartEg {
public static void main(String[] args) {
final int i = 8; //定义一个final类型的局部变量。
class person {
public String name;
public void show() { //内部类方法
System.out.println(i);
System.out.println(this.name);
}
}
person p = new person();
p.name = "Jackson";
p.show();
}
}
运行结果:
方法中内部类只能访问方法中的final类型的局部变量,而不能访问其他类型的局部变量,但可以访问部类的所有数据成员和成员方法。
- 匿名内部类
Java允许创建对象的同时定义类的实现,但是未规定类名,Java将其定义为匿名内部类。适用情况:只需创建一个 类的对象并且用不上它的名字时,或者说有的内部类只需要创建一个它的对象,以后不会用到这个类。
语法规则:
new interfacename(){...};
或 new superclassname(){...};
实例:
方法count()使用匿名内部类直接返回了一个实现了接口Contents的类的对象。
public interface Contents {
int value();
}
public class Test1 {
public Contents cont(){
return new Contents(){ //返回值的生成及表示返回值的类的定义
private int i = 11;
public int value(){
return i;
}
}; //分号
}
}
注意:
匿名内部类因为没有名字,所以她没有构造方法。但如果该匿名内部类继承了一个只含有带参数构造方法的父类,创建它的时候就必须带上这些参数,并在实现过程中使用super关键字调用相应内容。
如果要初始化它的数据成员,可采用下面几种方法:
(1)如果是一个方法的匿名内部类,通过这个方法传进需要的参数,同时这些参数不许被声明为final。
(2)将匿名内部类改造成有名字的局部内部类,这样这个类就可以拥有构造方法了。
(3)在匿名内部类中使用初始化代码块。