基本概念
在类内部进行其他类结构嵌套操作
class Outer{
private String msg = "Hello World" ;
// ********************************
class Inner{ //定义一个内部类
public void print(){ //定义一个普通方法
System.out.println(msg); //调用msg属性
}
}
// ********************************
//在外部类中定义一个方法,该方法负责产生内部类对象并且调用print()方法
public void fun(){
Inner in = new Inner(); //内部类对象
in.print(); // 内部类提供的print()方法
}
}
public class Test{
public static void main(String[] args) {
Outer out = new Outer(); //外部类对象
out.fun(); //外部类方法
}
}
引入内部类后,程序的结构有些混乱。虽然内部类破坏了程序的结构,但是从另一方面 来讲,内部类可以方便的操作外部类的私有访问。
内部类的优点
-
内部类与外部类可以方便的访问彼此的私有域(包含私有方法、私有属性)
-
内部类是另外一种封装(保护性),对外部是其他类隐藏
-
内部类可以实现Java单继承的局限(多继承)
class A {
private String name = "A类的私有域";
public String getName() {
return name;
}
}
class B {
private int age = 20;
public int getAge() {
return age;
}
}
class Outter {
//内部类
//--------------------------------------------
private class InnerClassA extends A {
public String name() {
return super.getName();
}
}
private class InnerClassB extends B {
public int age() {
return super.getAge();
}
}
//--------------------------------------------
public String name() {
return new InnerClassA().name();
}
public int age() {
return new InnerClassB().age();
}
}
public class Test {
public static void main(String[] args) {
Outter outter = new Outter();
System.out.println(outter.name());
System.out.println(outter.age());
}
}
缺点:结构复杂
内部类与外部类的关系
-
对于非静态内部类,内部类的创建需要依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的
-
内部类是一个相对独立的个体,与外部类没有 isa关系
-
内部类可以直接访问外部类的元素(包含私有栈),但是外部类不可以直接访问内部类元素,需要通过内部类的引用间接访问
class Outter {
private String msg;
private int age;
//----------------------------------------
class Inner {
public void Display(){
msg = "test"; //相当于Outter.this.msg="test"
age = 20; //相当于Outter.this.age=20
System.out.println(msg);
System.out.println(age);
}
}
//----------------------------------------
public void test(){
Inner in = new Inner();
in.Display();
}
}
public class Test {
public static void main(String[] args) {
Outter out = new Outter();
out.test();
}
}
创建内部类语法(在外部类内部)
-
创建非静态内部类
外部类.内部类 内部类引用 = new 外部类(). new 内部类 Outter.Inner in = new Outter().new Inner();
-
创建静态内部类
外部类.内部类 内部类引用 = new 外部类(). 内部类 Outter.Inner in = new Outter().Inner();
内部类的分类
成员内部类(类比成员方法)
-
成员内部类不能存在任何static变量或方法,但是可以访问外部类的静态域
-
成员内部类是依附外部类的,所以只有先创建了外部类才能创建内部类
class Outter {
private String msg = "test";
private static int age = 30;
class Inner {
public void test(){
//private static int age = 20; //错误,成员内部类不能存在任何static变量或方法
System.out.println(msg);
System.out.println(age);
}
}
}
public class Test {
public static void main(String[] args) {
Outter.Inner in= new Outter().new Inner();
in.test();
}
}
静态内部类(类比静态方法)
-
静态内部类的创建不需要依赖外部类,可以直接创建
-
静态内部类不可以使用任何外部类的非static域(包含属性与方法),但是存在自己的成员变量
class Outter {
private String msg = "test";
private static int age = 30;
static class Inner {
private static int age = 20;
public void test(){
// System.out.println(msg); 错误,无法从静态上下文中引用非静态变量 msg
System.out.println(age);
}
}
}
public class Test {
public static void main(String[] args) {
Outter.Inner in= new Outter.Inner();
in.test();
}
}
方法内部类
方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是它们的作用域不同,方法内部类只能在该方法中被使用,出了该方法就会失效。 对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。
- 方法内部类不允许使用任何访问权限修饰符
public private protected 均不允许
- 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问
- 方法内部类如果要想使用方法形参,该形参必须使用final声明(JDK8将形参变为隐式final声明)
class Outter {
private String msg = "test";
public void test(final int temp){
//方法内部里,不能使用任何访问权限修饰符
class Inner{
public void fun(){
System.out.println(msg);
//temp++; //错误,从内部类引用的本地变量必须是最终变量或实际上的最终变量
System.out.println(temp);
}
}
new Inner().fun();
}
}
public class Test {
public static void main(String[] args) {
Outter out = new Outter();
out.test(20);
}
}
匿名内部类(lamdba表达式前身)
匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束。除此之外,还有一些地方需要注意:
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类是没有构造方法的,因为它没有类名
- 匿名内部类中不能存在任何静态成员或方法
- 匿名内部类是没有访问修饰符的
- 与局部内部相同匿名内部类也可以引用方法形参。此形参也必须声明为 final
//声明一个接口
interface MyInterface {
void test();
}
class Outter {
private int num = 5;
public void display(int para) {
// 匿名内部类,匿名的实现了MyInterface接口
new MyInterface(){
@Override
public void test() {
System.out.println("匿名内部类"+para);
}
}.test();
}
}
public class Test {
public static void main(String[] args) {
Outter outter = new Outter();
outter.display(20);
}
}