Java 内部类
一.内部类定义
内部类就是在某个类的内部又定义了一个类,被内部类嵌入的类称为外部类。
Java内部类分为四种
- 成员内部类:在外部类中直接定义的内部类。即内部类定义在外部类域的位置。
- 局部内部类:在外部类的方法中定义的内类。
- 静态内部类:当static修饰内部类时,内部类就相当于外部类的一个静态属性。
- 匿名内部类:在类中需要实例化这个类的地方(通常为方法内),定义了一个没有名称的类。
四种内部类的共性
- 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的的类名和$符号。
- 内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由的访问外部类的成员变量,无论是否是private。
- 内部类声明成静态的,就不能随意访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量。
二.四种内部类分析
1.成员内部类
作为外部类的一个成员存在,与外部类的所有属性,方法并列。
package exercise;
class Outer {
private String index="The String is in Outer Class";
class Inner{
String index="The String is in Inner Class";
void print(){
String index="The String is in print Method";
System.out.println(index);
System.out.println(this.index);
System.out.println(Outer.this.index);
}
}
}
public class part_InteriorClass{
public static void main(String[] args){
Outer outer=new Outer();
Outer.Inner inner=outer.new Inner();
inner.print();
}
}
运行结果显示
The String is in print Method
The String is in Inner Class
The String is in Outer Class
编译后生成文件如下:
分析:
成员内部类Inner前无修饰符或修饰符为public,protected都可以在测试函数中采用上述程序中“Outer.Inner
inner=outer.new
Inner();” 语句进行生成内部类对象。
成员内部类Inner前有修饰符private时,需要使成员内部类继承抽象类或接口,并通过外部类的特定函数实现成员内部类的
一个实例。示例程序如下:
package exercise;
abstract class Pinner{
abstract void print();
}
class Outer {
private String index="The String is in Outer Class";
private class privateInner extends Pinner{
String index="The String is in privateInner Class";
void print(){
String index="The String is in privateInner-print-Method";
System.out.println(index);
System.out.println(this.index);
System.out.println(Outer.this.index);
}
}
privateInner getInner()
{
return new privateInner();
}
}
public class part_InteriorClass{
public static void main(String[] args){
Outer outer=new Outer();
Pinner pinner=outer.getInner();
pinner.print();
}
}
运行结果显示
The String is in privateInner-print-Method
The String is in privateInner Class
The String is in Outer Class
编译后生成文件如下:
2.局部内部类
内部类定义在方法体内时,只能访问方法体内的常量,而不能访问方法体内的局部变量,且方法体内的内部类前没有任何修饰
符。
package exercise;
public class method_InneriorClass {
private String s="我是外部类的私有变量";
class partclass {
public void show1() {
System.out.println("成员内部类的test方法");
}
}
public void exercise(){
final String member ="我是局部变量";//方法内的变量只有final变量才能被方法内部类访问
System.out.println("这里是:外部类的成员函数");
class methodclass extends partclass{
public void show2(){
System.out.println("测试局部内部类可以访问方法体内的局部变量:"+member);
System.out.println("测试是否可以访问外部类的private变量s:"+s);
}
}
new methodclass().show1();//方法内部类里的方法只能在方法里调用
new methodclass().show2();
}
public static void main(String[] args) {
new method_InneriorClass().exercise();
}
}
运行结果显示
这里是:外部类的成员函数
成员内部类的test方法
测试局部内部类可以访问方法体内的局部变量:我是局部变量
测试是否可以访问外部类的private变量s:我是外部类的私有变量
编译后生成的文件如下
分析:
上述程序中partclass类为成员内部类,methodclass类为exercise方法中的局部内部类,并且局部内部类methodclass继承成
员内部类partclass.
3.静态内部类
当static修饰内部类时,则它一定是成员内部类(因为局部内部类前无任何修饰符),此时内部类相当于外部类的一个静态属
性,内部类中可以有static属性或方法。static内部类不能使用外部类的非static的属性或方法,且static内部类产生对象实例也有自
己的特点。
package exercise;
class Outer1 {
static private String Oindex="The String is in Outer Class";
static class staticInner{
String index="The String is in staticInner Class";
void print(){
String index="The String is in print Method";
System.out.println(index);
System.out.println(this.index);
System.out.println(Oindex);
}
}
}
public class static_InteriorClass{
public static void main(String[] args){
Outer1.staticInner staticinner=new Outer1.staticInner();
staticinner.print();
}
}
运行结果显示
The String is in print Method
The String is in staticInner Class
The String is in Outer Class
编译后生成的文件如下
分析:
上述程序中staticInner为静态内部类,它只能访问外部类的静态成员(属性或方法),并且静态内部类产生对象实例需要使用
语句“Outer1.staticInner staticinner=new Outer1.staticInner();”
注意:
如果在外部类的静态方法static main()中通过“Inner inner=new Inner()”语句直接生成内部类的对象,则内部类需要是static
修饰的静态内部类,或将内部类写在main方法中,并放在“Inner inner=new Inner()”之前。
示例程序如下:
a. main方法调用静态内部类
package exercise;
public class main_callInteriorClass {
private String name="outer";
public static void main(String argv[]){
Inner inner=new Inner();
inner.showName();
}
public static class Inner{
String name=new String("Inner");
void showName(){
System.out.println(name);
}
}
}
运行结果显示
Inner
编译后生成的文件如下
package exercise;
public class main_callInteriorClass {
private String name="outer";
public static void main(String argv[]){
class Inner{
String name=new String("Inner");
void showName(){
System.out.println(name);
}
}
Inner inner=new Inner();
inner.showName();
}
运行结果显示
Inner
编译后生成的文件如下
c. 错误调用内部类
package exercise;
public class main_callInteriorClass {
private String name="outer";
public static void main(String argv[]){
Inner inner=new Inner();//不可以直接调用内部类
inner.showName();
}
public class Inner{
String name=new String("Inner");
void showName(){
System.out.println(name);
}
}
}
匿名内部类就是在类中需要实例化这个类的地方(通常为方法内),定义一个没有名称的类。
匿名内部类的使用规则
1)匿名内部类不能有构造方法,但是这个匿名内部类继承了一个只含有带参数构造方法的父类,在创建它的对象的时候,在括号中必须带上这些参数。
2)匿名内部类不能定义任何静态成员和方法。
3)匿名内部类能被public、protected、private、static修饰。
4)只能创建匿名内部类的一个实例。
匿名内部类的使用条件
1)只用到类的一个实例。
2)类在定义后马上用到。
3)类非常小(Sun推荐是4行代码以下)。
package exercise;
public class anonymity_IntertorClass {
public static void main(String [] args){
Object obj=new Object(){
public int hashCode(){
return 1;
}
};
System.out.println(obj.hashCode());
}
}
运行结果显示
1
编译后生成的文件如下
分析:
上述示例程序中,新建了一个Object的子类,在Main()函数中只写了子类的定义,没有子类的名字,并且匿名类对Object
类的hashCode方法进行了覆盖。
补充:
a. 匿名内部类继承抽象类
package exercise;
abstract class Anonymity
{
abstract public void fun1();
}
public class extend_abstract_anonymityInteriorClass {
public static void main(String[] args){
new extend_abstract_anonymityInteriorClass().callInner(new Anonymity(){
public void fun1(){
System.out.println("匿名内部类测试");
}
}
);
}
public void callInner(Anonymity a){
a.fun1();
}
}
运行结果显示
匿名内部类测试
编译后生成的文件如下
b. 将上述程序修改为有名的内部类,则示例如下
package exercise;
abstract class Anonymity
{
abstract public void fun1();
}
public class extend_abstract_anonymityInteriorClass {
public void callInner(Anonymity a){
a.fun1();
}
public static void main(String[] args){
class inner extends Anonymity{
public void fun1(){
System.out.println("匿名内部类测试");
}
}
new extend_abstract_anonymityInteriorClass().callInner(new inner());
}
}
匿名内部类测试
编译后生成的文件如下
c. 匿名内部类实现接口
package exercise;
public class implement_inerface_anonymityInteriorClass {
public static void main(String[] args){
new Thread(new Runnable(){
public void run(){
System.out.println("run");
}
}).start();
}
}
run
编译后生成的文件如下
分析:
Runnable为JDK中定义线程执行内容的接口,通过匿名内部类的方式产生了 一个实现Runnable接口的对象。