内部类
从开发角度来说,尽量不要使用内部类
内部类基本概念
1.内部类是指在一个类的内部定义其他的类。
范例:内部类
class Outer { // 外部类
private String msg = "Hello World";
class Inner { // 内部类
public void print() {
System.out.println(msg);
}
}
public void fun() {
// 实例化内部类对象,调用print()方法
new Inner().print();
}
}
public class Demo {
public static void main(String[] args) {
// 实例化外部类对象
Outer out = new Outer();
out.fun(); // 调用外部类方法,Hello World
}
}
上述代码牺牲了程序的结构,实现了一个重要功能。
2.为说明内部类特点,现将内部类取出,作为一个单独的类,并要求实现与之前一样的功能。
范例:取出内部类
class Outer {
private String msg = "Hello World";
public void fun() {
new Inner().print();
}
}
class Inner {
public void print() {
System.out.println(msg);
}
}
public class Demo {
public static void main(String[] args) {
Outer out = new Outer();
out.fun(); // 报错,msg属于Outer,Inner无法调用
}
}
(1)要想使得Inner
调用msg
,就需在Outer
中写一个getMsg()
public String getMsg(){
return this.msg;
}
(2)Inner
要调用Outer
的getMsg()
方法,必须实例化一个Outer
对象
class Outer {
private String msg = "Hello World";
public String getMsg(){
return this.msg;
}
public void fun() {
new Inner().print();
}
}
class Inner {
public void print() {
System.out.println(new Outer().getMsg());
}
}
public class Demo {
public static void main(String[] args) {
Outer out = new Outer();
out.fun();
}
}
上述的做法不合理,最好是将主方法中的Outer对象传递给Inner对象。
class Outer {
private String msg = "Hello World";
public String getMsg() {
return this.msg;
}
public void fun() {
new Inner(this).print();
}
}
class Inner {
private Outer out;
public Inner(Outer out) {
this.out = out;
}
public void print() {
System.out.println(this.out.getMsg());
}
}
public class Demo {
public static void main(String[] args) {
Outer out = new Outer();
out.fun();
}
}
由此可得内部类的特点:
内部类可以直接访问外部类的私有属性和方法,外部类也可以通过内部类对象访问内部类的私有属性。
范例:访问内部类私有属性
class Outer { // 外部类
private String msg = "Hello World";
class Inner { // 内部类
private String info = "世界你好";
public void print() {
System.out.println(msg);
}
}
public void fun() {
// 实例化内部类对象
Inner in = new Inner();
// 使用内部类对象访问内部类私有属性
System.out.println(in.info);
}
}
public class Demo {
public static void main(String[] args) {
Outer out = new Outer();
out.fun();
}
}
3.观察代码
class Outer { // 外部类
private String msg = "Hello World";
class Inner { // 内部类
private String info = "世界你好";
public void print() {
System.out.println(this.msg); // 报错,找不到msg
}
}
public void fun() {
new Inner().print();
}
}
报错原因:this.msg
指向的是Inner
类,而Inner
类中没有msg
属性。因此要访问Outer
的msg
属性,需要使用Outer.this.msg
.
class Outer { // 外部类
private String msg = "Hello World";
class Inner { // 内部类
public void print() {
// 外部类.this = 外部类的当前对象
System.out.println(Outer.this.msg);
}
}
public void fun() {
new Inner().print();
}
}
4.内部类的class文件名: Outer$Inner.class
直接实例化内部类对象语法:外部类.内部类 对象名 = new 外部类().new 内部类();
范例:实例化内部类对象
public class Demo {
public static void main(String[] args) {
Outer.Inner in = new Outer().new Inner();
in.print();
}
}
上述代码说明:
要想使用内部类对象,必须先实例化外部类对象。开发中一般是通过外部类访问内部类,不用创建内部类对象。
5.内部类只想被外部类使用,不能被外部调用,应使用private
定义
class Outer { // 外部类
private String msg = "Hello World";
private class Inner { // 内部类
public void print() {
// 外部类.this = 外部类的当前对象
System.out.println(Outer.this.msg);
}
}
}
static定义内部类
使用static定义的属性或方法不受实例化对象控制,因此使用static定义的内部类也不受外部类实例化对象控制。
1.static定义的内部类只能访问外部类中static定义的属性或方法
class Outer { // 外部类
private String msg = "Hello World";
static class Inner { // 内部类
public void print() {
System.out.println(msg); // 报错,无法引用非静态变量msg
}
}
}
2.static定义的内部类,相当于外部类
取得static定义的内部类对象语法:外部类.内部类 对象 = new 外部类.内部类();
由该语法可知,static定义的内部类,不需要先实例化外部类对象,再实例化内部类对象,相当于内部类成了一个外部类。
class Outer { // 外部类
private static String msg = "Hello World";
static class Inner { // 内部类
public void print() {
System.out.println(msg);
}
}
}
public class Demo {
public static void main(String[] args) {
Outer.Inner in = new Outer.Inner();
in.print();
}
}
方法中定义内部类
1.内部类可定义在外部类中的任意位置。在方法中定义内部类是最常见的形式。
class Outer { // 外部类
private String msg = "Hello World";
public void fun() {
class Inner { // 定义在方法中的内部类
public void print() {
System.out.println(msg);
}
}
new Inner().print();
}
}
public class Demo {
public static void main(String[] args) {
new Outer().fun();
}
}
2.方法可以接收参数,也可以定义变量
范例:访问方法中定义的参数或变量
class Outer { // 外部类
private String msg = "Hello World";
public void fun(int num) { // 方法参数
double score = 99.9; // 方法变量
class Inner { // 定义在方法中的内部类
public void print() {
System.out.println("属性:" + msg);
System.out.println("方法参数:" + num);
System.out.println("方法变量:" + score);
}
}
new Inner().print();
}
}
public class Demo {
public static void main(String[] args) {
new Outer().fun(100);
}
}
方法中的内部类可以访问方法中未用关键字修饰的参数或变量,该操作仅限于JDK1.8后!在JDK1.8之前的版本严格要求:方法中的内部类只能访问final
标记的参数或变量,所以上述代码在JDK1.7前应该改为如下形式:
class Outer { // 外部类
private String msg = "Hello World";
public void fun(final int num) { // 方法参数
final double score = 99.9; // 方法变量
class Inner { // 定义在方法中的内部类
public void print() {
System.out.println("属性:" + msg);
System.out.println("方法参数:" + num);
System.out.println("方法变量:" + score);
}
}
new Inner().print();
}
}
匿名内部类
interface Message {
public void print();
}
class Messagelmpl implements Message {
public void print() {
System.out.println("Hello");
}
}
public class Demo {
public static void main(String[] args) {
fun(new Messagelmpl());
}
public static void fun(Message msg) {
msg.print();
}
}
假如Messagelmpl
只使用一次,那么就可以利用匿名内部类。
范例:使用匿名内部类
interface Message {
public void print();
}
public class Demo {
public static void main(String[] args) {
fun(new Message() {
// 匿名内部类
public void print() {
System.out.println("Hello");
}
});
}
public static void fun(Message msg) {
msg.print();
}
}
使用匿名内部类的前提:必须基于接口或抽象类的应用。
匿名内部类定义在方法中,方法的参数或是变量要被匿名内部类访问,必须加上final
关键字。匿名内部类的优点在于减少了类的定义。