Java内部类
2016-01-21 10:36
489 查看
什么事内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类。public class OuterClass{ private String name; private int age; public String GetName(){ return name; } public void SetName(String name){ this.name = name; } public int GetAge(){ return age; } public void SetAge(int age){ this.age = age; } class InterCalss{ public InterClass(){ name = "quanquan"; age = "23"; } } }
在这里InterClass就是内部类。
为什么使用内部类
为什么使用内部类?在《Think in java》中有这样一句话:使用内部类最吸引人的原因是:每个内部类都能独立的继承一个(接口的)实现,所以无论外部类是否已经继承了某个(接口)实现,对于内部类都没有影响。 在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。
public interface Father{ } public interface Mather{ } public class Son implements Father,Mather{ } public class Daughter implements Father{ class Mather_ implements Mather{ } }
起始对于上面的实例我们看不出内部类有什么优点,但是如果Father和Mather不是接口而是抽象类或者是具体的类呢?这时候我们只能使用内部类实现多继承了。 其实使用内部类最大的优点就在于它能够非常好的解决重继承问题,但如果我们不需要解决重继承问题,那么我们自然可以使用其他编码方式,但是使用内部类还能为我们带来如下特性: 1.内部类可以使用对公实例,每个实例都有自己的状态信息,并且与其他外部类对象的信息相互独立。 2.在单个外部类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。 3.创建内部类对象的时刻并不依赖于外部类对象的创建。 4.内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。 5.内部类提供了更好的封装,除了该外部类,其他类都不能访问。
内部类基础
在这个部分主要介绍内部类如何使用外部类的属性和方法,以及使用.this与.new。 当我们在创建一个内部类的时候,它无形中就与外部类有了一种联系,依赖于这种联系,它可以无限制的访问外部类的元素。
public class OuterClass{ private String name; private int age; //省略getter和setter方法 public class InterClass{ public InterClass(){ name = "quanquan"; age = "23"; } public void Display(){ System.ou,println("name"+ GetName()+"age:"+GetAge()); } } public static void main(){ OuterClass outer = new OuterClass(); OuterClass.InterClass inter = outer.new InterClass(); inter.Display(); } }
从上述实例中我们可以看出,内部类InterClass可以对外部类OuterClass的属性进行无缝的访问,尽管它是private修饰的。这是因为我们在创建某个外部类的内部类对象时,此时内部类对象必定会捕获一个指向那个外部类对象的引用,只要我们在访问外部类的成员时,就会用到这个引用来选择外部类的成员。 其实在这个应用程序中我们还看到了如何来引用内部类:引用内部类我们需要指明这个对象的类型:OuterClassName.InterClassName,同时如果我们需要创建某个内部类对象,必须要利用外部类的对象通过.new来创建内部类:OuterClassName.InetrClassName inetr = outer.new InterClassName(); 同时如果我们需要生成对外部类对象的引用,可以使用OuterClassName.this,这样就能够产生一个正确引用外部类的引用了。当然这点在编译期就知晓了,没有任何运行时的成本。
public class OuterClass{ public void display(){ System.out.println("OuterClass..."); } public class InterClass(){ public OuterClass getOuterClass(){ return OuterClass.this; } } public static void main(){ OuterClass outer = new OuterClass(); OuterClass.OnterClass inter = outer.new InterClass(); inter.getOuterClass().display(); } }
到了这里我们需要明确一点,内部类是编译时期的概念,一旦编译成功后,它就与外部类隶属于两个完全不同的类。对于一个名为OuterClass的外部类和一个名为InterCalss 的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class 和OuterClass$InterClass.class。 在java中内部类主要分为成员内部类、局部内部类、匿名内部类、静态内部类。
成员内部类
成员内部类也是普通的内部类,它是外部类的一个成员,所以它是可以无限制的访问外部类的所有成员属性和方法,尽管是private的,但是外部类要访问内部类的成员属性和方法则需要通过内部类的实例来访问。 在成员内部类中要注意两点,第一:成员内部类中不能存在任何static的变量和方法;第二:成员内部类依附于外部类,所以创建了外部类才能创建内部类。
public class OuterClass{ private String str; public void outerDisplay(){ System.out.println("OuterClass..."); } public class InterClass{ public void interDisplay(){ str = "quanquan..."; System.out.println(str); outerDisplay(); } } //推荐使用getXXX()来获取成员内部类,尤其是该内部类的构造函数无参时 public InterClass getInterClass(){ return new InterClass(); } public static void main(){ OuterClass outer = new OuterClass(); OuterClass.InterClass inter = outer.new InterClass(); inter.interDisplay(); } }
局部内部类
有这样一种内部类,它是嵌套在方法中的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所有就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中使用,出了该方法和属性就会失效。
//定义在方法里面 public void Parcel5(){ public Destionation destionation(String str){ class PDestionation implements Destionation { private String label; private PDestionation(String whereTo){ label = whereTo; } public String readLabel(){ return label; } } return new PDestionation (str); } public static void main(){ Parcel5 parcel5 = new Parcel5(); Destionation d = parcel5.destionation("chenssy"); } } //定义在作用域内 public class Parcel6(){ 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(quanquan); String string = ts.getSlip(); } } public void track(){ internalTracking(true); } public static void main(){ Parcel6 parcel6 = new Parcel6(); parcel6.track(); } }
匿名内部类
在Swing编程中,我们经常使用这种方式来绑定事件。
button2.addActionListenter{ new ActionListenter(){ public void actionPerformed(ActionEvent e){ System.out.println("您按了按钮二"); } } }
我们乍一看可能觉得奇怪,因为这个内部类没有名字,在看看下面的列子:
public class OuterClass{ public InterClass getInterClass(final int num,String str2){ return new InterClass(){ int number = num+3; public int getNumber(){ return number; } }; } public static void main(){ OuterClass out = new OuterClass(); InterClass inter = outer.getInterClass(2,"quanquan"); System.out.println(inter.getNumber()); } } interface InterClass{ int getNumber(); }
这里我们需要开清楚几个地方 1.匿名内部类是没有访问修饰符的。 2.new 匿名内部类,这个类首先是要存在的。如果我们将那个InterClass接口注释掉,就会出现编译错误。 3.注意getInterClass()方法的形参,第一个参数是用final修饰的,而第二个参数却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个参数必须是用final修饰的。 4.匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。
静态内部类
在关键字static中提到static可以修饰成员变量、方法、代码块,其他它还可以修饰内部类,使用static修饰的内部类称之为静态内部类,或者称为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后或隐含的保存一个引用,该引用指向创建它的外部类内,但静态内部类却没有。没有这个引用就意味着: 1.它的创建不需要依赖于外部类。 2.它不能使用任何外部类的非static成员变量和方法。
public class Outerlass{ private String sex; public static String name = "quanquan"; //静态内部类 static class InterClass{ //在静态内部类可以存在静态成员 public static String name_1 = "quanquan_static" public void display(){ //静态内部类只能访问外部类的静态方法和成员,不能访问非静态方法和成员 System.out.println("Outer name "+ name): } } //非静态内部类 class InterClass{ //非静态内部类中不能访问外部类中静态成员和方法 public String name_2 = "quanquan_inter" //非静态内部类可以调用外部类的任何成员,不管静态还是非静态 public void display(){ System.out.println("OuterClass neme"+ name); } } //外部类方法 public void display(){ //外部类访问静态内部类 System.out.println("InterClass.name_1"); //静态内部类可以直接创建实例不需要依赖于外部类 new InterClass().display(); //非静态内部类的创建需要依赖于外部类 OuterClass. } }
相关文章推荐
- 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简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树