您的位置:首页 > 编程语言 > Java开发

朝花夕拾——Java的内部类

2015-07-29 14:39 411 查看
Java的内部类,之前一直没有弄明白,在公司的学习文档中看到《安卓内存泄露—尽量不要持有activity的context》的标题,继而涉及匿名内部类,而关于内部类,之前一直没有系统的学习,因此而恶补。

java内部类的优点:

内部类可以很好的实现隐藏(有private,protected权限),即封装性

内部类拥有外围类的所有元素的访问权限,包括私有变量

可是实现多重继承(解决了java的单继承缺陷)

可以避免修改接口而实现同一个类中两种同名方法的调用

(链接 — 这个博客说的很详细:http://andy136566.iteye.com/blog/1061951/

java内部类的缺点(个人总结,欢迎指正):

降低了代码的复用

过多的使用降低了代码可读性

不恰当的使用会产生许多静态的合成方法,影响性能

说了辣么多,现在该介绍我们的内部类了~

java内部类

成员内部类

局部内部类

静态内部类

匿名内部类

成员内部类

我喜欢从例子到结论,所以先来看看一下的demo

public class Outer {
private static int year=2015;
private String str="巴拉拉";
private int  i=2
public final  float Pi=(float) 3.14;

public static void main(String[] args) {
Outer outer = new Outer();
//你可以这样子实例化一个内部类
Outer.Inner inner = outer.new Inner();
inner.print();
//也可以这样~
inner = outer.getInner();
inner.print();
}

//外部类的方法,如果方法名与内部类相同,则不能再内部类调用,否则会出现死循环(不断调用自己)
public void sayHi() {
System.out.println("Hello");
}

// 个人推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时
public Inner getInner() {
return new Inner();
}

public class Inner {
//变量名可以和外部类一样~
private int  i=2015
//private static int i =100; //编译不通过,不允许出现静态变量

public void print() {
sayHi();
//你还可以访问外部类的变量,而且管他什么修饰符
System.out.println(str+" "+year+" "+Pi);
System.out.println(str+"  "+Outer.i+" "+Pi);
}
}
}


上传不了图片。。。。总之结果就是输出了:

巴拉拉 2015 3.14

巴拉拉 2 3.14

sss

从上所得以下几个结论

成员内部类使用层级与外部类的属性,方法是并列的,即都可以通过 “. ”来直接调用

成员内部类可以直接获取外部类的属性,方法(注意:外部类的方法若与内部类相同,则内部类调用的是自身)

即使成员内部类定义的参数与外部类参数名相同,也可以与外部类共存,在无指定的情况下内部类调用内部类自身的变量。

成员内部类不允许有静态变量,因为成员内部类需要先创建了外部类,才能创建它自己的

局部内部类

我喜欢从例子到结论,所以先来看看一下的demo,有两个demo~,来自Think In Java

demo 1:

public class Parcel4 {

public Destination destination(String s) {
final String str="test";//不加final 会报错
//在方法里声明内部类
class PDestination implements Destination {
private String label;

private PDestination() {
label = str;
}

public String readLabel() {
return str;
}
}
return new PDestination();
}

public static void main(String[] args) {
Parcel4 p = new Parcel4();
Destination d = p.destination("Tasmania");
}
}


demo 2:

public class Parcel5 {
private void internalTracking(boolean b) {
if (b) {
//在作用域里声明内部类
class TrackingSlip {
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() {
return id;
}
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
}

public void track() {
internalTracking(true);
}

public static void main(String[] args) {
Parcel5 p = new Parcel5();
p.track();
}
}


前情提要:方法中定义的变量是局部变量,只在供给方法自身调用(即作用域只在方法内),因此是不能用修饰词来修饰的,概括:static只存在类中,而不是在方法里

从上所得以下几个结论:

局部内部类与成员内部类一样是先要实例化外部类,进而实例化自身

局部内部类是不能定义静态变量的

若局部内部类调用作用域内或方法内的参数,则该参数一定是final的

在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。要想使用局部内部类时需要生成对象,对象调用方法,在方法中才能调用其局部内部类。通过内部类和接口达到一个强制的弱耦合,用局部内部类来实现接口,并在方法中返回接口类型,使局部内部类不可见,屏蔽实现类的可见性,见demo1

静态内部类

我喜欢从例子到结论,所以先来看看一下的demo。

public class Outer {
String name="Outer";

static class Inner{
static int i = 100;
String name="Inner";
void sayHello(){

// System.out.println(Outer.name+"Hello"); 报错不能访问外部类非静态变量
System.out.println(name+"Hello");
sayHello2();
}
}
static void sayHello2(){
// System.out.println(Outer.name+"Hello"); 报错不能访问外部类非静态变量
System.out.println("Hello");
}
public static void main(String args[]){
// 静态内部类的静态参数或方法可以直接调用
System.out.println(Inner.i);
//静态内部类的非静态参数或是方法需要实例化静态内部类
Inner inner=new Inner();
System.out.println(inner.name);
}
}


从上所得以下几个结论:

静态内部类静态内部类只能访问外部类的静态成员,包括静态变量和静态方法

静态内部类不需要通过外部类来实例化,可以看做是同外部类同样的类(顶级类)

匿名内部类

http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html

结论:

因为没有名字,所以匿名内部类只能使用一次

若匿名内部类需要传入参数,且传入的参数被内部使用,则需要定义为fianl (原因如下:“内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。)

使用匿名内部类有个前提条件:必须继承一个父类或实现一个接口
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java