Java内部类详解.doc_第1页
Java内部类详解.doc_第2页
Java内部类详解.doc_第3页
Java内部类详解.doc_第4页
Java内部类详解.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一、内部类详解1、定义 一个类的定义放在另一个类的内部,这个类就叫做内部类。 Java代码 1. publicclassFirst2. publicclassContents3. publicvoidf()4. System.out.println(InClassFirstsinnerClassContentsmethodf();5. 6. 7. public class First public class Contents public void f()System.out.println(In Class Firsts inner Class Contents method f(); 像这样的,Contents就叫做内部类 内部类了解外围类,并能与之通信(后面详细讲) 2、链接到外围类 创建了内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件。 Java代码 1. publicclassFirst2. publicclassContents3. publicvoidgetStr()4. System.out.println(First.str=+str);5. 6. 7. privateStringstr;8. 9. public class First public class Contents public void getStr()System.out.println(First.str=+str); private String str; 在内部类Contents中,可以使用外围类First的字段str。 那么,它是如何实现的呢? 是这样的,用外围类创建内部类对象时,此内部类对象会秘密的捕获一个指向外围类的引用,于是,可以通过这个引用来访问外围类的成员。 通常,这些都是编译器来处理,我们看不到,也不用关心这个。 正是因为如此,我们创建内部类对象时,必须与外围类对象相关联。 注:嵌套类(后面会讲到)除外。 3、使用关键字.this与.new 内部类中得到当前外围类对象的引用,可以使用.this关键字,注意与new的区别 Java代码 1. privateintnum;2. publicTest2()3. 4. 5. 6. publicTest2(intnum)7. this.num=num;8. 9. 10. privateclassInner11. publicTest2getTest2()12. returnTest2.this;13. 14. 15. publicTest2newTest2()16. returnnewTest2();17. 18. 19. 20. publicstaticvoidmain(Stringargs)21. Test2test=newTest2(5);22. Test2.Innerinner=test.newInner();23. Test2test2=inner.getTest2();24. Test2test3=inner.newTest2();25. System.out.println(test2.num);26. System.out.println(test3.num);27. 28. private int num ;public Test2()public Test2(int num)this.num = num;private class Innerpublic Test2 getTest2()return Test2.this;public Test2 newTest2()return new Test2();public static void main(String args)Test2 test = new Test2(5);Test2.Inner inner = test.new Inner();Test2 test2 = inner.getTest2();Test2 test3 = inner.newTest2();System.out.println(test2.num);System.out.println(test3.num); 输出结果为5 0 使用.this后,得到时创建该内部类时使用的外围类对象的引用,new则是创建了一个新的引用。 .new关键字 如果想直接创建一个内部类对象,而不是通过外围类对象的方法来得到,可以使用.new关键字 形式是这样的: Java代码 1. OutClass.InnerClassobj=outClassInstance.newInnerClass(); OutClass.InnerClass obj = outClassInstance.new InnerClass(); 必须是外围类对象.new,而不能是外围类.new Java代码 1. publicclassFirst2. publicclassContents3. publicvoidf()4. System.out.println(InClassFirstsinnerClassContentsmethodf();5. 6. publicvoidgetStr()7. System.out.println(First.str=+str);8. 9. 10. 11. publicstaticvoidmain(Stringargs)12. Firstfirst=newFirst();13. First.Contentscontents=first.newContents();14. contents.f();15. 16. 17. public class First public class Contentspublic void f()System.out.println(In Class Firsts inner Class Contents method f();public void getStr()System.out.println(First.str=+str);public static void main(String args)First first = new First();First.Contents contents = first.new Contents();contents.f(); 必须通过外围类First的对象first来创建一个内部类的对象 而且需要注意的是,在创建外围类对象之前,不可能创建内部类的对象(嵌套类除外)。 4、内部类与向上转型 将内部类向上转型为基类型,尤其是接口时,内部类就有了用武之地。 Java代码 1. publicinterfaceShape2. publicvoidpaint();3. 4. publicclassPainter5. 6. privateclassInnerShapeimplementsShape7. publicvoidpaint()8. System.out.println(painterpaint()method);9. 10. 11. 12. publicShapegetShape()13. returnnewInnerShape();14. 15. 16. publicstaticvoidmain(Stringargs)17. Painterpainter=newPainter();18. Shapeshape=painter.getShape();19. shape.paint();20. 21. 22. public interface Shape public void paint(); public class Painter private class InnerShape implements Shapepublic void paint()System.out.println(painter paint() method);public Shape getShape()return new InnerShape(); public static void main(String args)Painter painter = new Painter();Shape shape = painter. getShape();shape.paint(); 此时,内部类是private的,可以它的外围类Painter以外,没人能访问。 这样,private内部类给累的设计者提供了一种途径,通过这种方式可以完全阻止任何依赖于类型的编码,并完全隐藏实现的细节。 5、方法内的类 可以在方法内创建一个类。 Java代码 1. publicvoidtest()2. assInner3. publicvoidmethod()4. ystem.out.println(在方法内创建的类);5. 6. 7. public void test()class Inner public void method()System.out.println(在方法内创建的类); 值得注意的是:方法内创建的类,不能加访问修饰符。 另外,方法内部的类也不是在调用方法时才会创建的,它们一样也被编译了(怎么知道的?后面会有讲解)。 6、匿名内部类 Java代码 1. publicclassPainter2. ublicShapegetShape()3. returnnewShape()4. publicvoidpaint()5. System.out.println(painterpaint()method);6. 7. ;8. 9. publicstaticvoidmain(Stringargs)10. Painterpainter=newPainter();11. Shapeshape=painter.getShape();12. shape.paint();13. 14. 15. publicinterfaceShape16. ublicvoidpaint();17. public class Painter public Shape getShape()return new Shape()public void paint()System.out.println(painter paint() method); public static void main(String args) Painter painter = new Painter(); Shape shape = painter.getShape(); shape.paint(); public interface Shape public void paint(); 注意,匿名内部类后面的分号不可缺少! 匿名类,顾名思义,就是没有名称。 getShape()方法里,就使用了匿名内部类。 看上去很奇怪,不符合传统的写法? 第一眼看上去确实是这样的。 这样写,意思是创建了一个实现了Shape的匿名类的对象。 匿名类可以创建,接口,抽象类,与普通类的对象。创建接口时,必须实现接口中所有方法。 这是无参的,如果需要参数呢? 可以直接传。 Java代码 1. publicclassB2. publicAgetA(intnum)3. returnnewA(num)4. 5. ;6. 7. 8. publicclassA9. privateintnum;10. publicA(intnum)11. this.num=num;12. 13. publicA()14. 15. 16. 17. public class B public A getA(int num)return new A(num); public class A private int num;public A(int num)this.num = num;public A() Ok,在这个例子中,可以为A的构造方法传入一个参数。在匿名内部类中,并没有使用到这个参数。 如果使用到了这个参数,那么这个参数就必须是final的。 Java代码 1. publicclassB2. publicAgetA(finalintnum)3. returnnewA(num)4. publicintgetNum()5. returnnum;6. 7. ;8. 9. 10. publicclassA11. privateintnum;12. publicA(intnum)13. this.num=num;14. 15. publicA()16. 17. 18. 19. public class B public A getA(final int num)return new A(num) public int getNum() return num; ; public class A private int num;public A(int num)this.num = num;public A() 如果不是final的,编译器就会提示出错。 另外,还可以在匿名内部类里定义属性 由于类是匿名的,自然没有构造器,如果想模仿构造器,可以采用实例初始化() Java代码 1. publicAgetA()2. returnnewA()3. intnum=0;4. Stringstr;5. 6. str=javaeye;7. System.out.println(hellorobbin);8. 9. ;10. 11. public A getA()return new A()int num = 0;String str;str = javaeye;System.out.println(hello robbin); 匿名内部类通过实例初始化,可以达到类似构造器的效果 另外可以通过匿名内部类来改造工厂方法。 Java代码 1. publicinterfaceService2. publicvoidmethod1();3. 4. publicinterfaceServiceFactory5. ServicegetService();6. 7. publicclassImplemention1implementsService8. publicvoidmethod1()9. System.out.println(InImplemention1methodmethod1();10. 11. 12. publicstaticServiceFactoryfactory=newServiceFactory()13. publicServicegetService()14. returnnewImplemention1();15. 16. ;17. 18. publicclassImplemention2implementsService19. publicvoidmethod1()20. System.out.println(inImplemention2methodmethod1();21. 22. 23. publicstaticServiceFactoryfactory=newServiceFactory()24. publicServicegetService()25. returnnewImplemention2();26. 27. ;28. 29. 30. publicclassTest31. publicstaticvoidmain(Stringargs)32. service(Implemention1.factory);33. service(Implemention2.factory);34. 35. ServiceFactoryfactory1=Implemention1.factory;36. Serviceservice1=factory1.getService();37. service1.method1();38. 39. ServiceFactoryfactory2=Implemention1.factory;40. Serviceservice2=factory2.getService();41. service2.method1();42. 43. public interface Service public void method1(); public interface ServiceFactory Service getService(); public class Implemention1 implements Servicepublic void method1()System.out.println(In Implemention1 method method1();public static ServiceFactory factory = new ServiceFactory()public Service getService()return new Implemention1(); public class Implemention2 implements Service public void method1()System.out.println(in Implemention2 method method1();public static ServiceFactory factory = new ServiceFactory()public Service getService()return new Implemention2(); public class Test public static void main(String args)service(Implemention1.factory);service(Implemention2.factory);ServiceFactory factory1 = Implemention1.factory;Service service1 = factory1.getService();service1.method1();ServiceFactory factory2 = Implemention1.factory;Service service2 = factory2.getService();service2.method1(); 在Implemention1和2中匿名内部类用在字段初始化地方。 这样定义的工厂方法,代码上看起来是不是优雅一些? 7、嵌套类 static的内部类就叫做嵌套类 前面提到了很多次,嵌套类是个例外 使用嵌套类时有两点需要注意: a、创建嵌套类对象时,不需要外围类 b、在嵌套类中,不能像普通内部类一样访问外围类的非static成员 Java代码 1. publicclassStaticClass2. privateintnum;3. privatestaticintsum=2;4. privatestaticclassStaticInnerClass5. publicintgetNum()6. /只能访问sum,不能访问num7. returnsum;8. 9. 10. 11. publicclassTest12. publicstaticvoidmain(Stringargs)13. /可以直接通过new来创建嵌套类对象14. StaticClass.StaticInnerClassinner=newStaticClass.StaticInnerClass();15. inner.getNum();16. 17. public class StaticClass private int num;private static int sum = 2;private static class StaticInnerClass public int getNum()/只能访问sum,不能访问num return sum; public class Test public static void main(String args) /可以直接通过new来创建嵌套类对象StaticClass.StaticInnerClass inner = new StaticClass.StaticInnerClass();inner.getNum(); 另外,嵌套类还有特殊之处,就是嵌套类中可以有static方法,static字段与嵌套类,而普通内部类中不能有这些。 8、内部类标识符 我们知道每个类会产生一个.class文件,文件名即为类名 同样,内部类也会产生这么一个.class文件,但是它的名称却不是内部类的类名,而是有着严格的限制:外围类的名字,加上$,再加上内部类名字。 前面说到得定义在方法内的内部类,不是在调用方法时生成,而是与外围类一同编译,就可以通过查看.class文件的方式来证明。 9、为何要内部类? a、内部类提供了某种进入外围类的窗户。 b、也是最吸引人的原因,每个内部类都能独立地继承一个接口,而无论外围类是否已经继承了某个接口。 因此,内部类使多重继承的解决方案变得更加完整。 在项目中,需要多重继承,如果是两个接口,那么好办,接口支持多重继承。 如果是两个类呢?这时只有使用内部类了。 Java代码 1. publicinterfaceOne2. publicvoidinOne();3. 4. publicinterfaceTwo5. publicvoidinTwo();6. 7. /两个接口,用普通类就可实现多重继承8. publicclassCommonClassimplementsOne,Two9. publicvoidinOne()10. System.out.println(CommonClassinOne()method);11. 12. 13. publicvoidinTwo()14. System.out.println(CommonClassinTwo()method);15. 16. 17. publicabstractclassThree18. publicabstractvoidinThree();19. 20. publicabstractclassFour21. publicabstractvoidinFour();22. 23. /两个抽象类,使用普通类无法实现多重继承24. 25. /使用内部类可以实现26. publicclassContentsextendsThree27. publicvoidinThree()28. System.out.println(InContentsinThress()method);29. 30. 31. publicclassInnerFourextendsFour32. publicvoidinFour()33. System.out.println(InContents);34. 35. 36. 37. 38. public interface One public void inOne(); public interface Two public void inTwo(); /两个接口,用普通类就可实现多重继承 public class CommonClass implements One,Two public void inOne()System.out.println(CommonClass inOne() method);public void inTwo()System.out.println(CommonClass inTwo() method); public abstract class Three public abstract void inThree(); public abstract class Four public abstract void inFour(); /两个抽象类,使用普通类无法实现多重继承 /使用内部类可以实现 public class Contents extends Three public void inThree()System.out.println(In Contents inThress() method);public class InnerFour extends Fourpublic void inFour()System.out.println(In Contents); 另外,还有好多地方可以使用内部类。读过hibernate源代码的同学,应该可以发现,里面有好多内部类。 最常见的内部类,应该是Map.Entry了,可以看看源代码 总结: 内部类的特性大致就是上述了,特性很直观,了解了之后,使用也很简单。 但是,何时使用我说的并不是很明确,因为本人知识有限,使用内部类也不是很多。项目中很少用,好像就是ActiveMQ那里用了一些。 不过,相信大家在了解了内部类的特性之后,再随着时间的推移,慢慢积累经验,应该会做出自己的判断,会在何时使用内部类,怎样应用了。二、内部类的作用1.内部类可以很好的实现隐藏 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以2内部类拥有外围类的所有元素的访问权限3.可是实现多重继承4.可以避免修改接口而实现同一个类中两种同名方法的调用。三、 例子1.实现隐藏 平时我们对类的访问权限,都是通过类前面的访问修饰符来限制的,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以,所以我们能通过内部类来隐藏我们的信息。可以看下面的例子接口package insidecategory;public interface Incrementable void increment();具体类package insidecategory;public class Example private class InsideClass implements InterfaceTest public void test() System.out.println(这是一个测试); public InterfaceTest getIn() return new InsideClass(); 上面加粗的部分是内部类,访问修饰符是private客户端程序package insidecategory;public class TestExample public static void main(String args) Example a=new Example(); InterfaceTest a1=a.getIn(); a1.test(); 加粗的那部分就是客户端调用的代码,从这段代码里面我只知道Example的getIn()方法能返回一个InterfaceTest 实例但我并不知道这个实例是这么实现的。而且由于InsideClass 是private的,所以我们如果不看代码的话根本看不到这个具体类的名字,所以说它可以很好的实现隐藏。2.可以无条件地访问外围类的所有元素package insidecategory;public class TagBean private String name=liutao; private class InTest public InTest() System.out.println(name); public void test() new InTest(); public static void main(String args) TagBean bb=new TagBean(); bb.test(); 看上面加粗部分,name这个变量是在TagBean里面定义的私有变量。这个变量在内部类中可以无条件地访问System.out.println(name);3.可以实现多重继承 个特点非常重要,个人认为它是内部类存在的最大理由之一。正是由于他的存在使得Java的继承机制更加完善。大家都知道Java只能继承一个类,它的多重继承在我们没有学习内部类之前是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了。它可以使我们的类继承多个具体类或抽象类。大家看下面的例子。类一 package insidecategory;public class Example1 public String name() return liutao; 类二package insidecategory;public class Example2 public int age() return 25; 类三package insidecategory;public class MainExample private class test1 extends Example1 public String name() return (); private

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论