<span style="font-family: Arial, Helvetica, sans-serif;"> </span><span style="font-family: Arial, Helvetica, sans-serif;">昨天,一位自学java的朋友问我内部类重不重要,我的回答当然是”很重要的“。当时我才意识到,对于这部分的知识已有所遗忘,所以有必要写一些测试代码,并将其记录下来。</span>
为什么要用内部类?这是一个很现实的问题,如果不知道内部类能做什么,那么学习起来就会有些漫无目的,觉着很迷茫。
对于内部类,我首先想到的一个用处就是解决java不能多继承的问题,当然也还有其它的作用,比如掩藏类的实现细节(这个读起来有点抽象,我们有个术语叫封装性)。
先来看一个很简单的一般内部类定义:
package com.pht.inner;
public class Outer {
class Inner{
}
}
可以看到,我们先定义了一个外部类Outer,然后在这个外部类里边又定义了一个类Inner,这个Inner就是一个内部类。
下边来看第一个问题:一般内部类能否直接访问外部类的私有属性和方法,可以自己写段代码来试试:
package com.pht.inner;
public class Outer {
private String arg1;
private void function1(){
}
class Inner{
public Inner() {
// TODO Auto-generated constructor stub
System.out.println(arg1);
function1();
}
}
}
在eclipse中这段代码是不会报错的,说明并没有语法错误(可能我这么说不太严谨)。可以写个Main方法来测试一下
package com.pht.inner;
import com.pht.inner.Outer.Inner;
public class TestMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
Inner inner=new Outer().new Inner();
}
}
输出结果如下:
说明答案就是一般内部类可以直接访问外部类的私有属性和私有方法。
下一个问题就是:如何创建一般内部类的对象
其实在上边的main方法中,已经创建内部类对象。应该注意到.new关键字。创建内部类对象的方法是:外部类实例.new 内部类类名();
第三个问题:外部类如何访问内部类以及它的属性和方法?我们来改造以上的方法,而且把属性和方法都设置为private的,如下:
public class Outer {
private String arg1;
public Outer() {
// TODO Auto-generated constructor stub
this.arg1="私有属性值";
Inner inner=new Inner();
inner.innerArg="内部类属性值2";
inner.printInnerArg();
}
private void function1(){
System.out.println("输出私有属性值:"+arg1);
}
class Inner{
private String innerArg;
public Inner() {
// TODO Auto-generated constructor stub
//System.out.println(arg1);
//function1();
this.innerArg="内部类属性值";
}
private void printInnerArg(){
System.out.println(innerArg);
}
}
}
通过运行,这段代码输出的是:内部类属性值2。所以可以确定,我们可以在外部类中直接用new来实例化一个内部类,且这个实例可以访问private型的属性和方法。那么先的问题又来了,假如内部类的属性和外部类的属性名称一样,内部类访问这个同名的外部类属性,会不会产生冲突?
package com.pht.inner;
public class Outer {
private String arg1;
private String sameArg;
public Outer() {
// TODO Auto-generated constructor stub
this.arg1="私有属性值";
this.sameArg="外部的同名属性";
Inner inner=new Inner();
inner.innerArg="内部类属性值2";
inner.printInnerArg();
}
private void function1(){
System.out.println("输出私有属性值:"+arg1);
}
class Inner{
private String innerArg;
private String sameArg;
public Inner() {
// TODO Auto-generated constructor stub
//System.out.println(arg1);
//function1();
this.innerArg="内部类属性值";
this.sameArg="内部的同名属性";
}
private void printInnerArg(){
System.out.println(innerArg);
System.out.println(sameArg);
}
}
}
这么写代码没有什么问题,那么System.out.println(sameArg)输出的应该是什么呢?正确答案是:内部的同名属性。所以它就近输出了内部属性的值,换成
System.out.println(this.sameArg)输出的也是内部属性值,因为这个this指的是当前内部类的实例。那么如果想输出外部类属性值该怎么办呢?很简单只需要要输出的属性名换成:外部类名.this.属性名,所以上面的输出行要改为:System.out.println(Outer.this.sameArg);
这里引出了一个新问题:.this的作用及用法。.this主要用在内部类引用外部类实例的情况下,比如说内部类调用一个以外部类实例为参数的方法,那么这个参数的实参就可以写为:外部类名.this。
这部分说了这么多,还是没有提现出来内部类的意义。留给下篇罢了。