1 内部类的基本定义
在类内部除了可以定义成员变量与方法外,还可定义另一个类。如果类 Outter 的内部再定义一个类 Inner,此时类 Inner 就称为内部类,而类 Outter 则称为外部类。
内部类可声明为 public 或 private。当内部类声明成 public 或 private 时,对其访问的限制与成员变量和成员方法完全相同。内部类的声明格式如下:
标识符 class 外部类的名称{
// 外部类成员
标识符 class 内部类的名称{
// 内部类成员
}
}
实例 1 代码:
package self.learn.innerclass;
public class Outer { // 定义外部类
private String info = "hello world!!!"; // 定义外部类私有属性
class Inner{ // 定义内部类
public void print() { // 定义内部类
System.out.println(info); // 直接访问外部类私有属性
}
}
public void fun() { // 定义方法
new Inner().print(); // 通过内部类对象调用方法
}
}
package self.learn.innerclass;
public class InnerClassDemo {
public static void main(String[] args) {
new Outer().fun(); // 调用外部类方法
}
}
运行结果截图:
从上面的程序中可以清楚的发现,Inner 类作为 Outer 类的内部类存在,并且在外部类的 fun()方法之中直接实例化内部类的对象并调用方法 print(),但是从上面的代码之中可以明显的发觉内部类实际上已经破坏了一个类的基本结构,因为类是由方法及属性组成的,这是内部类的一个缺点。,如果现在把内部类拿到外面就可以发现内部类的优点,如下代码:
实例 2 代码:
package self.learn.innerclass;
public class Outer { // 定义外部类
private String info = "hello world!!!"; // 定义外部类私有属性
public String getInfo() { // 取得私有属性
return this.info;
}
public void fun() {
new Inner(this).print(); // 将当前对象传递到 Inner 中
}
}
package self.learn.innerclass;
public class Inner {
private Outer outer = null; // 声明外部类对象
public Inner(Outer outer) { // 接收外部类对象实例
this.outer = outer;
}
public void print() { // 打印外部类私有属性
System.out.println(outer.getInfo());
}
}
运行结果截图:
以上的程序完成了内部类同样的功能,但是代码明显比之前的更加复杂,所以内部类唯一好处就是可以方便地访问外部类中的私有属性。同时,外部类也可以方便地访问内部类中的私有属性,这样就可以避免封装所带来的的操作结果复杂的问题。
2 使用 static 定义内部类
使用 static 可以声明属性或方法,而使用 static 也可以声明内部类,用 static 声明的内部类则变成外部类,但是用 static 声明的内部类不能访问非 static 的外部类属性。
实例 3 代码:
package self.learn.innerclass;
public class Outer { // 定义外部类
private static String info = "hello world!!!"; // 定义外部类私有属性
static class Inner{ // 使用 static 定义内部类为外部类
public void print() { // 打印外部类私有属性
System.out.println(info);
}
}
}
package self.learn.innerclass;
public class InnerClassDemo {
public static void main(String[] args) {
new Outer.Inner().print(); // 访问内部类
}
}
运行结果截图:
以上程序将 info 属性定义成了 static 类型,这样程序中就可以通过 static 声明的内部类直接访问此 static 属性了,当然,如果此时 info 属性不是 static 类型的话,则编译时将出现以下的错误:
3 在外部类访问内部类
一个内部类除了可以通过外部类访问,也可以直接在其他类中进行调用,调用的基本格式为:
外部类.内部类 内部类对象 = 外部类实例.new 内部类()
以上的操作格式中,首先要找到外部类的实例化对象之后,才可以通过外部类的实例化对象去实例化内部类的对象。
实例 4 代码:
package self.learn.innerclass;
public class Outer { // 定义外部类
private String info = "hello world!!!"; // 定义外部类私有属性
class Inner{ // 使用 static 定义内部类为外部类
public void print() { // 打印外部类私有属性
System.out.println(info);
}
}
}
package self.learn.innerclass;
public class InnerClassDemo {
public static void main(String[] args) {
// Outer.Inner inner = new Outer().new Inner(); // 这种方式也可以
// inner.print();
Outer outer = new Outer(); // 实例化外部类对象
Outer.Inner inner = outer.new Inner(); // 实例化内部类对象
inner.print(); // 调用内部类方法
}
}
运行结果截图:
4 在方法中定义内部类
理论上,内部类可以定义在程序中的任何位置,例如:代码块、方法中,但是在方法中定义的内部类不能直接 访问方法中的参数,如果方法中的参数想被内部类访问,则参数前必须加上 final 关键字(JDK 1.8 以前需要加 final ,之后就不用加了)。
实例 5 代码:
package self.learn.innerclass;
public class Outer { // 定义外部类
private String info = "hello world!!!"; // 定义外部类私有属性
public void fun( int temp) { // jdk 1.8 之前方法参数前要加 final 关键字
class Inner{ // 在方法中定义内部类
public void print() { // 打印外部类私有属性
System.out.println("类中的属性:"+info);
System.out.println("方法中的参数:"+temp);
}
}
new Inner().print();
}
}
package self.learn.innerclass;
public class InnerClassDemo {
public static void main(String[] args) {
new Outer().fun(30);
}
}