朝花夕拾——Java的内部类
2015-07-29 14:39
411 查看
Java的内部类,之前一直没有弄明白,在公司的学习文档中看到《安卓内存泄露—尽量不要持有activity的context》的标题,继而涉及匿名内部类,而关于内部类,之前一直没有系统的学习,因此而恶补。
内部类拥有外围类的所有元素的访问权限,包括私有变量
可是实现多重继承(解决了java的单继承缺陷)
可以避免修改接口而实现同一个类中两种同名方法的调用
(链接 — 这个博客说的很详细:http://andy136566.iteye.com/blog/1061951/)
过多的使用降低了代码可读性
不恰当的使用会产生许多静态的合成方法,影响性能
说了辣么多,现在该介绍我们的内部类了~
局部内部类
静态内部类
匿名内部类
上传不了图片。。。。总之结果就是输出了:
巴拉拉 2015 3.14
巴拉拉 2 3.14
sss
从上所得以下几个结论
成员内部类使用层级与外部类的属性,方法是并列的,即都可以通过 “. ”来直接调用
成员内部类可以直接获取外部类的属性,方法(注意:外部类的方法若与内部类相同,则内部类调用的是自身)
即使成员内部类定义的参数与外部类参数名相同,也可以与外部类共存,在无指定的情况下内部类调用内部类自身的变量。
成员内部类不允许有静态变量,因为成员内部类需要先创建了外部类,才能创建它自己的
前情提要:方法中定义的变量是局部变量,只在供给方法自身调用(即作用域只在方法内),因此是不能用修饰词来修饰的,概括:static只存在类中,而不是在方法里
从上所得以下几个结论:
局部内部类与成员内部类一样是先要实例化外部类,进而实例化自身
局部内部类是不能定义静态变量的
若局部内部类调用作用域内或方法内的参数,则该参数一定是final的
在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。要想使用局部内部类时需要生成对象,对象调用方法,在方法中才能调用其局部内部类。通过内部类和接口达到一个强制的弱耦合,用局部内部类来实现接口,并在方法中返回接口类型,使局部内部类不可见,屏蔽实现类的可见性,见demo1。
从上所得以下几个结论:
静态内部类静态内部类只能访问外部类的静态成员,包括静态变量和静态方法
静态内部类不需要通过外部类来实例化,可以看做是同外部类同样的类(顶级类)
结论:
因为没有名字,所以匿名内部类只能使用一次
若匿名内部类需要传入参数,且传入的参数被内部使用,则需要定义为fianl (原因如下:“内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。)
使用匿名内部类有个前提条件:必须继承一个父类或实现一个接口
java内部类的优点:
内部类可以很好的实现隐藏(有private,protected权限),即封装性内部类拥有外围类的所有元素的访问权限,包括私有变量
可是实现多重继承(解决了java的单继承缺陷)
可以避免修改接口而实现同一个类中两种同名方法的调用
(链接 — 这个博客说的很详细:http://andy136566.iteye.com/blog/1061951/)
java内部类的缺点(个人总结,欢迎指正):
降低了代码的复用过多的使用降低了代码可读性
不恰当的使用会产生许多静态的合成方法,影响性能
说了辣么多,现在该介绍我们的内部类了~
java内部类
成员内部类局部内部类
静态内部类
匿名内部类
成员内部类
我喜欢从例子到结论,所以先来看看一下的demopublic 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 Javademo 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对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统