您的位置:首页 > 其它

内部类

2015-06-05 21:26 344 查看

内部类

在类内部定义的类我们称这个类为内部类。包含内部类的类叫做外部类。java从JDK1.1开始引入内部类。内部类的作用如下:

1,内部类提供了更好的封装,可以把内部类隐藏在外部类之内。

2,内部类可以访问外部类的私有数据,内部类其实就相当于外部类的成员(内部类成员),同一个类中成员和成员可以互相访问。

3,匿名内部类适合用于只需要创建一次或只需要使用一次的类。

内部类的细分

定义内部类非常简单,只需要把一个类放在类的内部即可。”类的内部”可以是类的任何位置,甚至是类中方法的内部(定义在方法中的内部类称为局部内部类)。在类中(就是{}中)称为成员内部类。我们一般都会使用成员内部类。局部内部类和匿名内部类都不属于类成员。

成员内部类分为两种:静态内部类和非静态内部类。

总的来说,内部类分为:成员内部类,局部内部类和匿名内部类。

非静态内部类

下面的程序在Cow类中定义了一个CowLeg内部类。内部类CowLeg访问了外部类的私有属性weight。

public class Cow {
private double weight;

public Cow(double weight){
this.weight = weight;
}

private class CowLeg{
private double length;
private String color;

public CowLeg(double length, String color){
this.length = length;
this.color = color;
}

public void info(){
System.out.println("length:"+length+"   color:"+color);
System.out.println("weight:"+weight);
}
}

public void test(){
CowLeg cowLeg = new CowLeg(12.1, "黑白猫熊色");
cowLeg.info();
}

public static void main(String [] args){
Cow cow = new Cow(123.4);
cow.test();
}
}


内部类可以访问外部类的属性,但是反过来外部类不能访问内部类的属性。因为一个内部类对象会默认依赖一个外部类对象,而外部类对象不一定包含一个内部类对象,什么时候包含内部类对象,要看代码的执行情况。

我们可以把CowLeg是类成员变量,一次他们四种访问权限:private、protected,不加任何访问修饰符(默认访问权限)、public。

最后一点需要注意的是:非静态内部类不能包含静态属性、静态方法和静态初始化块。

静态内部类

如果使用static来修饰一个内部类,那么这个类就是静态内部类。静态内部类可以看成是类的静态成员变量,静态内部类可以访问外部类的静态成员,但是不能访问外部类的非静态成员(这遵循着java静态成员不能访问非静态成员的规则)。即使是静态内部类的非静态方法也不能访问外部类的非静态成员,因为静态内部类是外部类相关的,静态内部类寄存在外部类的类本身,而不是外部类的实例对象,没有寄存对象就访问不到外部类的实例成员了。下面给出一个代码:

public class TestClassInnerClass {
private int prop1 = 5;
private static int prop2 = 9;

static class StaticClassInnerClass{
private int age;
private static int age1=25;
public static void accessOutputProp(){
System.out.println("可以访问外部类的static成员:"+prop2);
System.out.println("输出内部类的age1变量:"+age1);
//一下代码将编译错误,不允许访问外部类的实例成员
//          System.out.println(prop1);
}
}

public static void main(String [] args){
StaticClassInnerClass.accessOutputProp();
}
}


局部内部类

如果把一个内部类定义在方法里,则这个内部类就是一个局部内部类。局部内部类可以看作是局部变量,而局部变量没有访问修饰符,它的作用域范围就是方法内。局部变量也不能用static修饰,因为这样修饰并没有意义,java也是不允许这样修饰的。所有局部内部类只能在方法内使用,不能使用访问修饰符符修饰,也不能是static的。代码如下:

public class LocalInnerClass {

public static void main(String [] args){
class LocalClass{
public void print(){
System.out.println("LocalClass print()");
}
}

LocalClass lc = new LocalClass();
lc.print();
}
}


匿名内部类

匿名内部类适合创建那种只需要使用一次的类(可以理解成一次性产品)。匿名内部类不能重复使用。创建匿名内部类时就会创建该匿名内部类的实例。匿名内部类的格式如下:



关于匿名类有如下两条规则:

1,匿名类不能是抽象的,因为匿名类创建时会创建该匿名类的对象。

2,匿名类没有构造器,因为匿名类没有类名。但是匿名类可以有初始化块,可以用初始化快来代替构造器。

通过匿名类创建某个接口类型的变量,这也是匿名类经常使用的方式。代码如下:

public interface Command {

void process(int [] array);
}


public class ProcessArray {

public void proocess(int [] array, Command command){
command.process(array);
}

public static void main(String [] args){
m2();
}

public static void m2(){
ProcessArray pa = new ProcessArray();
int [] array = new int[]{1,2,-2,12,4};

//这里使用匿名内部类的方式创建了一个Command类型的对象
pa.proocess(array, new Command(){

@Override
public void process(int[] array) {
System.out.println(Arrays.toString(array));
}});
}
}


proocess()方法第一个参数是需要处理的数组,第二个参数是需要处理数组的方式,也就是处理数组需要调用的方法。为了演示匿名内部类的应用场景,我们假设将数组输出的这种方式只需要使用一次,使用匿名内部类代码显得更简洁(除了简洁个人没有发现其他好处)。

注意:匿名内部类不能是抽象的,所以需要实现接口或类中的所有抽象方法。匿名内部类也可以重新父类的方法,下面将会演示。

我们再来看一下创建某一个类 类型的匿名内部类,代码如下:

public abstract class Command {

public void process(int[] array) {
System.out.println(Arrays.toString(array));
endPrint();
}
public abstract void endPrint();
}


public class ProcessArray {

public void proocess(int [] array, Command command){
command.process(array);
}

public static void main(String [] args){
m2();
}

public static void m2(){
ProcessArray pa = new ProcessArray();
int [] array = new int[]{1,2,-2,12,4};

pa.proocess(array, new Command(){

//这匿名内部类重写了Command类的process()
@Override
public void process(int[] array) {
System.out.println(Arrays.toString(array));
endPrint();
}

//这匿名内部类实现了Command类的process()
@Override
public void endPrint() {
System.out.println("处理数组结束...");
}});
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  匿名内部类 隐藏