三、内部类
内部类是定义在另一个类中的类,使用内部类的原因如下:
①内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。
②内部类可以对同一个包中的其它类隐藏起来。
③当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。
每个内部类都能独立的继承一个(接口的)实现,无论外围类是否已经继承了某个(接口)的实现,对于内部类都没有影响
1、使用内部类访问对象的状态
内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。
在编译时,编译器将会为内部类生成一个默认的构造器,会添加一个外围类的引用参数。
public B(A a){
outer = a;
}
A是外围类,outer不是关键字,只是用它来说明内部类的机制。
2、内部类基础(语法规则)
public class OuterClass {
private String name ;
private int age;
/**省略getter和setter方法**/
public class InnerClass{
public InnerClass(){
name = "chenssy";
age = 23;
}
public void display(){
System.out.println("name:" + getName() +" ;age:" + getAge());
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}
①引用内部类时必须指明这个对象的类型
OuterClassName.InnerClassName
②创建内部类对象时
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
③需要生成对外部类对象的引用,可以使用OuterClassName.this
Note:内部类中声明的所有静态域都必须是final,因为对于每个外部类对象,都会分别有一个内部类的实例,如果这个域不是final,它可能就不是惟一的。
内部类不能有static方法
内部类是一种编译器现象,与虚拟机无关,编译器将会把内部类翻译成用$分隔外部类与内部类名的常规类文件
如:
OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$InnerClass.class
3、成员内部类
成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
Note:①成员内部类不能存在任何static的变量和方法,②成员内部类依附于外围类,只有创建了外围类才能创建内部类。
public class OuterClass {
private String str;
public void outerDisplay(){
System.out.println("outerClass...");
}
public class InnerClass{
public void innerDisplay(){
//使用外围内的属性
str = "chenssy...";
System.out.println(str);
//使用外围内的方法
outerDisplay();
}
}
/*推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时 */
public InnerClass getInnerClass(){
return new InnerClass();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.getInnerClass(); //也可以创建一个内部类对象来调用该内部类中的方法
inner.innerDisplay();
}
}
4、局部内部类
局部内部类是嵌套在方法和作用域内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。
它不能用public或private说明符进行声明。
①定义在方法里
public class Parcel5 {
public Destionation destionation(String str){
class PDestionation implements Destionation{
private String label;
private PDestionation(String whereTo){
label = whereTo;
}
public String readLabel(){
return label;
}
}
return new PDestionation(str);
}
public static void main(String[] args) {
Parcel5 parcel5 = new Parcel5();
Destionation d = parcel5.destionation("chenssy");
}
}
②定义在作用域内
public class Parcel6 {
private void internalTracking(boolean b){
if(b){
class TrackingSlip{ //定义一个局部内部类
private String id;
TrackingSlip(String s) { //构造器
id = s;
}
String getSlip(){
return id;
}
}
TrackingSlip ts = new TrackingSlip("chenssy");
String string = ts.getSlip();
}
}
public void track(){
internalTracking(true);
}
public static void main(String[] args) {
Parcel6 parcel6 = new Parcel6();
parcel6.track();
}
}
5、匿名内部类
button2.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("你按了按钮二");
}
});
①匿名内部类时没有访问修饰符的
②new 匿名内部类,这个类首先是存在的
③当匿名内部类要是用某个形参时,这个参数要被设置为final。
④匿名内部类没有构造方法。
6、静态内部类
使用static修饰的称为静态内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:
①它的创建不需要依赖外围类
②它不能使用任何外围类的非static成员变量和方法。
③与常规内部类不同,静态内部类可以由静态域和方法。
④声明在接口中的内部类自动成为static和public类。
public class OuterClass {
private String sex;
public static String name = "chenssy";
/**
*静态内部类
*/
static class InnerClass1{
/* 在静态内部类中可以存在静态成员 */
public static String _name1 = "chenssy_static";
public void display(){
/*
* 静态内部类只能访问外围类的静态成员变量和方法
* 不能访问外围类的非静态成员变量和方法
*/
System.out.println("OutClass name :" + name);
}
}
/**
* 非静态内部类
*/
class InnerClass2{
/* 非静态内部类中不能存在静态成员 */
public String _name2 = "chenssy_inner";
/* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
public void display(){
System.out.println("OuterClass name:" + name);
}
}
public void display(){
/* 外围类访问静态内部类:内部类. */
System.out.println(InnerClass1._name1);
/* 静态内部类 可以直接创建实例不需要依赖于外围类 */
new InnerClass1().display();
/* 非静态内部的创建需要依赖于外围类 */
OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
/* 方位非静态内部类的成员需要使用非静态内部类的实例 */
System.out.println(inner2._name2);
inner2.display();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display();
}
}