您的位置:首页 > 职场人生

黑马程序员-java内部类总结

2014-06-18 21:32 239 查看
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

内部类指在一个外部类的内部再定义一个类。

内部类可以用成员修饰符修饰,如static、public、friendly、protected和private。而外部顶级类(即类名和文件名相同的)也只能使用public和friendly。

1、成员内部类

1)成员内部类,就是作为外部类的成员,可以直接访问外部类的所有成员变量和方法,包括private的。因为内部类中持有一个外部类的引用,格式:OuterClass.this ;

2)外部类要访问内部类,必须建立内部类对象。

当内部类定义在外部类的成员位置上,且非私有,可以在外部其他类中直接建立内部类对象。

格式: OuterClass.InnerClass in=new OuterClass.new InnerClass();

3)注意,成员内部类中不能含有静态变量和方法。原因请见下面的“嵌套内部类”部分。

例1:

class  TestDemo
{
public static void main(String[] args)
{
Outer.Inner in1=new Outer().new Inner();//得到内部类的一种方式
in1.function();
Outer.Inner in2=new Outer().getInner();
in2.function();
}
}
class Outer
{
private int x=3;
class Inner
{
void function()
{
System.out.println("Inner:"+x);   //内部类可以访问外部类所有成员,包括私有的。
}
}
/*在外部类作用范围之外得到内部类对象的另一种方式,那就是利用其外部类的方法创建并返回。
个人推荐这种方式,尤其当内部类的构造函数无参数时*/
public Inner getInner()
{
return new Inner();
}
}


输出结果:

Inner:3
Inner:3

2、嵌套内部类

嵌套内部类,就是用static修饰的内部类。

1)当内部类被static修饰后,就具备static的特性,只能直接访问外部类中的static成员。出现了访问局限。

2)

在外部其他类,直接访问static内部类中的非静态成员的格式:new OuterClass.InnerClass().function();

在外部其他类,直接访问static内部类中的静态成员的格式:Outer.Inner.function();

3)当内部类中定义了静态成员,则该内部类必须是嵌套类的,而嵌套类中的成员不必都是静态的;当外部类中的静态方法访问内部类时,内部类也必须是嵌套类。

例2:

class  TestDemo
{
public static void main(String[] args)
{
new Outer.Inner().function1();  //在外部其他类,直接访问static内部类中的非静态成员
Outer.Inner.function2();        //在外部其他类,直接访问static内部类中的静态成员
}
}
class Outer
{
private int x=3;
private static int y=4;
static class Inner
{
void function1()
{
//System.out.println("Inner.x:"+x);   //出错,嵌套内部类只能访问外部类中的静态成员。
System.out.println("Inner.y="+y);
}
static void function2()
{
System.out.println("Inner.static");
}
}
}


输出结果:

Inner.y=4
Inner.static


3、局部内部类
局部内部类,是指内部类定义在方法和作用域内。

1)局部内部类仍可以访问外部成员

2)内部类以及其内部成员前面不能加private、static等修饰符。因为它们是用于修饰成员的,而此时内部类已经变成了局部变量;

3)局部内部类只能访问被final修饰的局部变量。                                                                                                                                                                                                  
                      例3:

class  TestDemo
{
public static void main(String[] args)
{
Outer out=new Outer();
out.method(1);
}
}
class Outer
{
private int x=3;

void method(final int a)
{
int b=4;
class Inner
{
void function()
{
//System.out.println("b="+b); //错误,局部内部类只能访问被final修饰的局部变量
System.out.println("a="+a);
System.out.println("x="+x);   //局部内部类仍可以访问外部成员
}
}
new Inner().function();
}
}


输出结果:

a=1
x=3

4、匿名内部类

1)匿名内部类其实就是内部类的简写格式

2)定义匿名内部类的前提:内部类必须是继承一个类或实现一个接口。换句话说,这个类或者接口要先定义;

3)匿名内部类的格式:new 父类\接口(){定义子类的内容};

4)其实匿名内部类就是一个匿名子类对象

5)匿名内部类中定义的方法最好不超过3个

6)匿名内部类是不能加修饰符的

例4:

class  TestDemo
{
public static void main(String[] args)
{
Outer out=new Outer();
out.method();
}
}
class Outer
{
private int x=3;

void method()
{
new Abs()
{
public void show()
{
System.out.println("x="+x);
}
}.show();
//调用接口中没有的方法也是可以的
new Abs()
{
public void show()
{
System.out.println("x="+x);
}
public void abs()
{
System.out.println("abs");
}
}.abs();
//当用父类\接口型引用变量指向匿名内部类时
Abs d=new Abs()
{
public void show()
{
System.out.println("x="+x);
}
public void abs()
{
System.out.println("abs");
}
};
d.show();
//d.abs();           //错误,根据java多态性可知
}
}
interface Abs
{
void show();
}


输出结果:

x=3
abs
x=3

5、内部类的作用

1)内部类可以很好的隐藏。因为内部类可以用private、protected等修饰;

2)内部类拥有外部类的所有成员的访问权限;

3)可以实现多重继承;

4)可以避免修改接口而实现同一个类中两种同名方法的调用。

下面针对各点作用举例说明,

例5:实现隐藏

class  TestDemo
{
public static void main(String[] args)
{
Outer out=new Outer();
Abs a=out.getAbs();
a.show();
}
}
class Outer
{
private class Inner implements Abs  //内部类私有化
{
private int i=1;
public void show()
{
System.out.println(i);
}
}
public Abs getAbs()               //返回值为内部类实现的接口类型
{
return new Inner();
}
}
interface Abs
{
void show();
}


输出结果:

1
此例中,内部类Inner被private修饰,它实现了接口Abs。在main中,通过getAbs()获得了内部类的对象,但是我们甚至连内部类的名字都没看到。因此内部类的第一个作用:隐藏不想让别人知道的操作,即封装性。

例6:可以访问外部类的所有成员

参见例1。

例7:可以实现多重继承

<
4000
pre class="java">class TestDemo
{
public static void main(String[] args)
{
Outer out=new Outer();
System.out.println("name="+out.getName());
System.out.println("age="+out.getAge());
}
}
class Outer
{
private class Inner1 extends A
{
public int getAge()
{
return super.getAge();
}
}
private class Inner2 extends B
{
public String getName()
{
return super.getName();
}
}
public int getAge()
{
return new Inner1().getAge();
}
public String getName()
{
return new Inner2().getName();
}
}
class A
{
public int getAge()
{
return 11;
}
}
class B
{
public String getName()
{
return "Zhangsan";
}
}

输出结果:

name=Zhangsan
age=11
通过内部类Inner1和Inner2分别继承了类A和B,我们类Outer就拥有了类A和B的成员变量和方法,也就是间接地实现了多继承。

例8:避免修改接口而实现同一个类中两种同名方法的调用

class Outer {} extends A implements B
class A
{
public int getAge()
{
return 11;
}
}
interface B
{
public int getAge();
}


如上所示,此时Outer类中,有两个同名的getAge()方法。既不能区别,重写时也不知道到底重写了哪一个。

而通过内部类即可解决这个问题:

class  TestDemo
{
public static void main(String[] args)
{
Outer out=new Outer();
System.out.println("A.age="+out.getAge());
System.out.println("B.age="+out.getInner().getAge());
}
}
class Outer extends A
{
private class Inner implements B
{
public int getAge()
{
return 20;
}
}
public B getInner()
{
return new Inner();
}
}
class A
{
public int getAge()
{
return 11;
}
}
interface B
{
public int getAge();
}

延伸阅读:

1)为什么内部类可以访问外部类的所有成员,包括私有的?

2)为什么在外部类的作用范围内可以任意创建内部类对象,即使内部类是私有的?即内部类对包围它的外部类可见。

3)为什么局部内部类只能访问被final修饰的局部变量?

4)为什么嵌套内部类(静态内部类)不能访问外部类的静态成员?

要了解到这些特点背后的机制,请参阅【解惑】领略Java内部类的“内部”这篇文章。

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com                                           
                         
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 内部类