Java Basics Part 20/20 - Inner Classes
目录
嵌套类
在 Java 中,在类中可以编写另外一个类。类中的类就叫做嵌套类(nested class),包含内部类的类就叫做外部类(outer class)。
语法
编写内部类的语法如下:
class Outer_Demo{
class Nested_Demo{
}
}
嵌套类分成两种形式:
- 非静态内部类:这些是类的非静态成员
- 静态内部类:这些是类的静态成员。
非静态内部类
内部类是 Java 安全机制的一种。Java 的类不可以有 private 这种访问级别,但是如果一个类中存在内部类,那么内部类就可以使 private 的了。
根据内部类定义的位置,可以分为三类:
- 内部类
- 方法内部类
- 匿名内部类
内部类
创建一个内部类是很easy的,只需要在类中编写另外一个类即可,但是与普通的类不同,内部类可以是 private 的,一旦将内部类声明为 private,那么在外部类类外部就无法访问这个内部类了。
例如下面这个程序,将内部类定义成 private 的,通过方法访问这个 private 的内部类:
class Outer_Demo{
int num;
//inner class
private class Inner_Demo{
public void print(){
System.out.println("This is an inner class");
}
}
//Accessing he inner class from the method within
void display_Inner(){
Inner_Demo inner = new Inner_Demo();
inner.print();
}
}
public class My_class{
public static void main(String args[]){
//Instantiating the outer class
Outer_Demo outer = new Outer_Demo();
//Accessing the display_Inner() method.
outer.display_Inner();
}
}
// output
This is an inner class.
访问私有成员
内部类还可以用来访问外部类的私有成员。在内部类中,定义一个方法 getValue() 来返回外部类的私有成员,然后第三方的类就可以使用 内部类的 getValue() 方法来访问外部类的私有成员了。
为了实例化内部类,要先实例化外部类,然后使用外部类对象的引用来实例化内部类。
Outer_Demo outer=new Outer_Demo();
Outer_Demo.Inner_Demo inner=outer.new Inner_Demo();
下面这个例子表明演示了怎样通过内部类来访问外部类的私有成员:
class Outer_Demo {
//private variable of the outer class
private int num= 175;
//inner class
public class Inner_Demo{
public int getNum(){
System.out.println("This is the getnum method of the inner class");
return num;
}
}
}
public class My_class2{
public static void main(String args[]){
//Instantiating the outer class
Outer_Demo outer=new Outer_Demo();
//Instantiating the inner class
Outer_Demo.Inner_Demo inner=outer.new Inner_Demo();
System.out.println(inner.getNum());
}
}
// output
The value of num in the class Test is: 175
方法内部类
在 Java 中,我们甚至可以在方法中编写一个类,那么这个类就变成了一个局部类型,就像局部变量一样,这个类的作用范围就是在方法中。
一个方法内部类只能在定义它的方法中实例化。举例:
public class Outerclass{
//instance method of the outer class
void my_Method(){
int num = 23;
//method-local inner class
class MethodInner_Demo{
public void print(){
System.out.println("This is method inner class "+num);
}
}//end of inner class
//Accessing the inner class
MethodInner_Demo inner = new MethodInner_Demo();
inner.print();
}
public static void main(String args[]){
Outerclass outer = new Outerclass();
outer.my_Method();
}
}
// output
This is method inner class 23
匿名内部类
顾名思义,没有名字的类就是匿名内部类,匿名内部类的声明和实例化是同时进行的。一般情况下,当需要重写一个类或者接口的方法时,需要用到匿名内部类。
AnonymousInner an_inner = new AnonymousInner(){
public void my_method(){
........
........
}
};
下面的例子演示了怎样使用匿名内部类来重写一个类的方法:
abstract class AnonymousInner{
public abstract void mymethod();
}
public class Outer_class {
public static void main(String args[]){
AnonymousInner inner = new AnonymousInner(){
public void mymethod(){
System.out.println("This is an example of anonymous inner class");
}
};
inner.mymethod();
}
}
// output
This is an example of anonymous inner class
同样,可以使用匿名内部类来重写一个接口实现类的方法。
使用匿名内部类作为参数
一般情况下,如果一个方法接收一个接口/抽象类/具体类的对象作为参数,那么我们就可以实现接口,继承抽象类,然后把对象传递给方法。但是如果它是一个类,那么我们可以直接传递给方法。
针对以上三种情况,均可以传递匿名内部类给方法。下面是语法:
obj.my_Method(new My_Class(){
public void Do(){
.....
.....
}
});
使用如下:
//interface
interface Message{
String greet();
}
public class My_class {
//method which accepts the object of interface Message
public void displayMessage(Message m){
System.out.println(m.greet() +", This is an example of anonymous inner class as an argument");
}
public static void main(String args[]){
//Instantiating the class
My_class obj = new My_class();
//Passing an anonymous inner class as an argument
obj.displayMessage(new Message(){
public String greet(){
return "Hello";
}
});
}
}
// output
Hello This is an example of anonymous inner class as an argument
静态嵌套类
静态内部类就相当于外部类的静态成员。与使用一般静态成员一样,不用实例化外部类就可以访问。同样,静态嵌套类不可以访问外部类的实例变量和实例方法。静态嵌套类的语法如下:
class MyOuter {
static class Nested_Demo{
}
}
实例化一个静态嵌套类与实例化内部类有点不同,如下:
public class Outer{
static class Nested_Demo{
public void my_method(){
System.out.println("This is my nested class");
}
}
public static void main(String args[]){
Outer.Nested_Demo nested = new Outer.Nested_Demo();
nested.my_method();
}
}
// output
This is my nested class