内部类
将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类
1、成员内部类
成员内部类内部类中最为简单的部分,就是在类A中再定义一个类B。显然类B必须在类A里面
public class Animal {
private String name;
public static int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//内部类,作为Animal类的一个成员
class Dog{
public void getVoice(){
age=1;
setName("旺财");
System.out.println(age+"岁的"+name+"发出\"汪汪\"的叫声");
}
}
}
从上面的代码可以看出Animal是Dog的外部类,Dog是Animal的内部类。重要的是成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
那么如何实例化成员内部类?如何调用它的成员?
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
public static void main(String[] args) {
//第一种方式
Animal animal = new Animal();
Animal.Dog dog1=animal.new Dog();
dog1.getVoice();
//第二种方式
Animal.Dog dog2=new Animal().new Dog();
dog2.getVoice();
}
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
现在我们已经知道了如何调用内部类成员,那么内部类如何访问外部类的成员?在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
public class Animal {
//实例化内部类
private Dog getInstance(){
return new Dog();
}
public void getAnimalVoice(){
//调用内部类的方法
getInstance().getVoice();
}
//内部类,作为Animal类的一个成员
class Dog{
public void getVoice(){
System.out.println("汪、汪、汪。。。。。");
}
}
}
2、局部内部类
在方法或者作用域里面定义的内部类叫做局部内部类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
与局部变量类似,局部内部类不能有访问说明符,因为它不是外围类的一部分,但是它可以访问当前代码块内的常量,和此外围类所有的成员。
需要注意的是:
(1)、局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
(2)、局部内部类对象不能使用该内部类所在方法的非final局部变量。
案例代码:
public class Fruit {
public Fruit() { }
}
class Apple{
public Apple(){}
public Fruit getOrange(){
//方法里面定义的类
class Orange extends Fruit{
String name="橘子";
public void printName(){
System.out.println(name);
}
}
return new Orange();
}
}
匿名内部类
匿名内部类就是没有名字的内部类。
如果满足下面的一些条件,使用匿名内部类是比较合适的:
- 只用到类的一个实例。
- 类在定义后马上用到。
- 类非常小(SUN推荐是在4行代码以下)
- 给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
- 匿名内部类不能有构造方法。
- 匿名内部类不能定义任何静态成员、方法和类。
- 匿名内部类不能是public,protected,private,static。
- 只能创建匿名内部类的一个实例。
- 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
- 因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
案例
//当我们想运用一个线程,但又不想自定义一个类通过继
//承Thread类来实现的时候,我们可以采用匿名内部类的实现方式
//这就是一个最为简单的匿名内部类
Thread thread=new Thread(){
@Override
public void run() {
System.out.println("我是一个匿名内部类的方法");
}
};
静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
案例
//定义
public class Fruit {
public Fruit() { }
static class Apple{
public Apple(){}
}
}
//实例化
Fruit.Apple apple=new Fruit.Apple();