内部类总结
来源:互联网 发布:复制淘口令淘宝没反应 编辑:程序博客网 时间:2024/06/06 02:01
在Java中,可以将一个类定义在另一个 类里面或者一个方法里面,这样的类称 为内部类。广泛意义上的内部类一般来 说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。
内部类的共性:
1、内部类仍然是一个独立的类,在编 译之后内部类会被编译成独立的.class 文件,但是前面冠以外部类的类名和$ 符号;
2、内部类不能用普通的方式访问。内 部类是外部类的一个成员,因此内部类 可以自由地访问外部类的成员变量,无 论是否是private的;
3、内部类声明成静态的,就不能随便 的访问外部类的成员变量了,此时内部 类只能访问外部类的静态成员变量。
成员内部类
成员内部类的基本应用:
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。 基本形式如下:
//外部类class Out { private int age = 12; //内部类 class In { public void print() { System. out.println(age ); } }}public class Demo { public static void main(String[] args) { Out.In in = new Out().new In(); in.print(); //或者采用下种方式访问 /* Out out = new Out(); Out.In in = out.new In(); in.print(); */ }}
运行结果:12
从上面的例子不难看出,内部类其实严重破坏了良好的代码结构,但为什么还要使用内部类呢?
因为内部类可以随意使用外部类的成员变量(包括私有)而不用生成外部类的对象,这也是内部类的唯一优点。
程序编译过后会产生两个.class文件,分别是Out.class和Out
Out.In in = new Out().new In()可以用来生成内部类的对象,这种方法存在两个小知识点需要注意:
1.开头的Out是为了标明需要生成的内部类对象在哪个外部类当中
2.必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量
内部类如何访问外部类的变量
不过要注意,当成员内部类拥有和外部 类同名的成员变量和方法时,会发生隐 藏现象,即默认情况下访问的是成员内 部类的成员,看下面这个例子:
class Out { private int age = 12; class In { private int age = 13; public void print() { int age = 14; System. out.println("局部变量:" + age); System. out.println("内部类变量:" + this. age); System. out.println("外部类变量:" + Out.this. age); } }}public class Demo { public static void main(String[] args) { Out.In in = new Out().new In(); in.print(); }}
运行结果:
局部变量:14
内部类变量:13
外部类变量:12
从上面的例子可以总结出,访问内部类本身的成员变量可用this.属性名的方式。而如果要访问外 部类的同名成员,需要使用以下方式:
1、外部类.this.成员变量
2、外部类.this.成员方法
外部类如何访问内部类的变量
在成员内部类中可以无条件的访问外部 类的成员,而外部类想访问成员内部类 的成员就有限制了。在外部类中,如果 要访问成员内部类的成员,必须先创建 一个成员内部类的对象,再通过指向这 个对象的引用来访问。看下面这个例子 :
class Circle { private double radius = 0; public Circle( double radius) { this.radius = radius; getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问 } private Draw getDrawInstance() { return new Draw(); } class Draw { //内部类 public void drawSahpe() { System. out.println(radius ); //外部类的private成员 } }}
成员内部类是依赖外部类存在的,如果要创建成员内部类的对象,则必须要有一个外部类的对象。 看下面这个例子,我们来总结一下成员内部类对象的创建方式:
class Out {//外部类 private In inner = null ; public Out() {} public In getInnerInstance() { if(inner == null) inner = new In(); return inner ; } class In { //内部类 public In() {} }}public class Test { public static void main(String[] args) { Out outter = new Out(); //第一种方式: Out.In inner = outter. new In(); //必须通过 Outter对象来创建 //等价于下面这种写法 Out.In inner = new Out().new In(); //第二种方式: Out.In inner1 = outter.getInnerInstance(); }}
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。
我们来看下面这个私有内部类的示例:
class Out { private int age = 12; private class In { public void print() { System. out.println(age ); } } public void outPrint() { new In().print(); }}public class Demo { public static void main(String[] args) { //此方法无效 /* Out.In in = new Out().new In(); in.print(); */ Out out = new Out(); out.outPrint(); }}
运行结果:12
上面的代码中,我们必须在Out类里面生成In类的对象进行操作,而无法再使用Out.In in = new Out().new In() 生成内部类的对象 。如果一个内部类只希望被外部类中的方法操作,那么可以使用private声明内部类。也就是说,此时的内部类只有外部类可控制。
局布内部类
局部内部类是定义在一个方法或者一个 作用域里面的类,它和成员内部类的区 别在于局部内部类的访问权限仅限于方 法内或者该作用域内。简而言之,局部 内部类就像是方法里面的一个局部变量 ,是不能有public、protected、 private以及static修饰符修饰的。我们来看下面的例子:
class Out { private int age = 12; public void Print(final int x) { class In { public void inPrint() { System. out.println(x); System. out.println(age ); } } new In().inPrint(); }}public class Demo { public static void main(String[] args) { Out out = new Out(); out.Print(3); }}
运行结果:
3
12
在上面的代码中,我们将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法。如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义。至于final在这里并没有特殊含义,只是一种表示形式而已。
匿名内部类
顾名思义,匿名内部类就是没有名字的内部类。表 面上看起来它们似乎有名字,但实际上那不是它们 的名字。程序中使用匿名内部类时,在定义匿名 内部类的地方往往直接创建该类的一个对象。使用 匿名内部类有个前提条件:必须继承一个父类或实 现一个接口。匿名内部类的声明格式如下:
//匿名内部类的声明格式new ParentName(){ //匿名内部类的定义}
为什么要使用匿名内部类?我们看下面一个例子, 当不使用匿名内部类时我们是这样实现抽象方法的 :
abstract class Person { public abstract void eat();}class Child extends Person { public void eat() { System. out.println("eat something" ); }}public class Demo { public static void main(String[] args) { Person p = new Child(); p.eat(); }}
可以看到,我们用Child继承了Person类,然后实 现了Child的一个实例,将其向上转型为Person类 的引用。但是,如果此处的Child类只使用一次, 那么将其编写为独立的一个类岂不是很麻烦?这个 时候就引入了匿名内部类。我们来看使用匿名内部 类我们怎么实现:
abstract class Person { public abstract void eat();}public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System. out.println("eat something" ); } }; p.eat(); }}
可以看到,我们直接将抽象类Person中的方法在大 括号中实现了。这样便可以省略一个类的书写。
什么情况下需要使用匿名内部类?如果满足下面的 一些条件,使用匿名内部类是比较合适的:
1、只用到类的一个实例 。
2、类在定义后马上用到。
3、类非常小(SUN推荐是在4行代码以下)
4、给类命名并不会导致你的代码更容易被理解
在使用匿名内部类时,要记住以下几个原则:
1、匿名内部类不能有构造方法。
2、匿名内部类不能定义任何静态成员、静态方法。
3、匿名内部类不能是 public,protected,private,static。
4、只能创建匿名内部类的一个实例。
5、一个匿名内部类一定是在new的后面,用其隐含 实现一个接口或实现一个类。
6、因匿名内部类为局部内部类,所以局部内部类 的所有限制都对其生效
1、继承式的匿名内部类
abstract class Person { public abstract void eat();}public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System. out.println("eat something" ); } }; p.eat(); }}
2、接口式的匿名内部类
好像是在实例化一个接口。事实并非如此,接口式 的匿名内部类是实现了一个接口的匿名类。而且只 能实现一个接口。我们看下面这个例子:
interface Person { public void eat();}public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System. out.println("eat something" ); } }; p.eat(); }}
只要一个类是抽象的或是一个接口,那么其子类中 的方法都可以使用匿名内部类来实现。最常用的情 况就是在多线程的实现上,因为要实现多线程必须 继承Thread类或是继承Runnable接口。
Thread类的匿名内部类实现
public class Demo { public static void main(String[] args) { Thread t = new Thread() { public void run() { for (int i = 1; i <= 5; i++) { System. out.print(i + " " ); } } }; t.start(); }}运行结果:1 2 3 4 5
Runnable接口的匿名内部类实现
public class Demo { public static void main(String[] args) { Runnable r = new Runnable() { public void run() { for (int i = 1; i <= 5; i++) { System.out.print(i + " "); } } }; Thread t = new Thread(r); t.start(); }}运行结果:1 2 3 4 5
3、参数式的匿名内部类
class Test{ static void go(){ Bar b = new Bar(); b.doStuff( new Foo(){ public void foo(){ System. out.println("foofy" ); } }); }}class Bar{ void doStuff(Foo f){ f.foo(); }}interface Foo{ void foo();}
关于匿名内部类的一个典型的应用就是Hibernate的HibernateCallBack,有兴趣的同学可以参看本人的另外一篇博客。
静态内部类
静态内部类也是定义在另一个类里面的类,只不过 在类的前面多了一个关键字static。静态内部类是 不需要依赖外部类的,这点和类的静态成员属性有 点类似,并且它不能是由外部类的非static成员变 量或者方法,这点很好理解,因为在没有外部类的 对象的情况下,可以创建静态内部类的对象,如果 允许访问外部类的非static成员就会产生矛盾,因 为外部类的非static成员必须依附于具体的对象。 我们来看下面的例子:
- 内部类总结
- java内部类总结
- Java内部类总结
- java内部类总结
- java内部类总结
- java内部类总结
- Java内部类总结
- java内部类总结
- Java内部类总结
- Java内部类总结
- Java内部类总结
- Java内部类总结
- 内部类的总结
- Java内部类总结
- Java内部类总结
- Java内部类总结
- Java内部类总结
- java内部类总结
- 斐波那契数列
- Spring Boot——开发新一代Spring Java应用
- 关于python中@property的使用
- Android性能优化之Battery-Historian(一)
- iOS- 浅谈视频播放的N种解决方案
- 内部类总结
- git+gerrit clone 脚本
- Read / Write Locks in Java
- Android 游戏编程
- [290] Word Pattern
- hdu5733 tetrahedron(计算几何)
- html前端几种加密方式的整理
- 红黑树知识点小结
- javaMail