目录
一、内部类是什么?
一个类定义在另一个类的内部,内部的内称之为内部类。
public class Outer{
class Inner{
}
}
二、内部类的特点
1.内部类可以很好的实现隐藏,可以使用protected、private修饰符。
2.内部类可以直接访问外部类的所有成员,包括私有的成员。
3.外部类不能直接访问内部类的成员,必须首先要建立内部类的对象才可访问。
4.内部类可以解决一些问题,比如间接地去实现多继承。可以避免修改接口而实现同一个类中两种同名方法的调用。
package com.aaa.test;
public class MemberInnerClassDemo {
public static void main(String[] args) {
Son son = new Son();
son.a();
son.a1();
}
}
abstract class ParentClass{
public abstract void a();
}
interface Ishow{
public abstract void a();
}
class Son extends ParentClass{
private class Inner3 implements Ishow{
@Override
public void a() {
System.out.println("我是接口中的a方法");
}
}
@Override
public void a() {
System.out.println("我是抽象类中的a方法");
}
public void a1(){
new Inner3().a();
}
}
三、成员内部类
特点
1.成员内部类属于外部类的实例成员,成员内部类可以有public,private,default,protected权限修饰符。在成员内部类中访问外部类的成员方法和属性, 要使用“外部类名.this.成员方法”和“外部类名.this.成员属性”的形式。
2.创建成员内部类的实例使用“外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)”的形式。
机制
1.成员内部类不能与外部类重名。
2.不能在成员内部类中定义static属性、方法和类(static final形式的常量定义除外)。因为一个成员内部类实例必然与一个外部类实例关联,static成员完全可以移到其外部类中去。
package com.aaa.test;
public class MemberInnerClass {
public static void main(String[] args) {
/*创建外部类*/
Outer1 outer1 = new Outer1();
/*创建了内部类的对象inner*/
Outer1.Inner1 inner1 = outer1.new Inner1();
inner1.innerShow1();
Outer1.Inner2 inner2 = outer1.new Inner2();
inner2.innerShow2();
}
}
class Outer1{
private String name = "张三";
private int age1 = 24;
public void outerShow(){
System.out.println(name);
System.out.println(age1);
}
public class Inner1{
private String name = "李四";
private int age2 = 25;
/*private static int age3 = 36;*//*在成员内部类中不能声明static类型的属性或方法*/
private static final int age4 =35;/*常量是可以的*/
public void innerShow1(){
System.out.println(name);
System.out.println(age2);
/*System.out.println(age1);*/
}
}
/*内部内可以调用外部类的成员方法和属性*/
public class Inner2{
public void innerShow2(){
System.out.println("--------------------------");
System.out.println("我调用了外部内的成员方法及属性");
System.out.println(Outer1.this.name);
System.out.println(Outer1.this.age1);
outerShow();
}
}
}
四、静态内部类
特点
1.使用static修饰的成员内部类叫静态内部类。
2.静态内部类跟外部类没有任何关系,只是在生成类名和类定义时有影响。静态内部类可以看做是与外部类平级的类。使用方式与外部类平级的类完全相同。
3.创建静态内部类的实例使用 外部类名.内部类名 实例名 = new 外部类名.内部类名(参数)。
机制
1.静态内部类不能与外部类重名。
2.静态内部类不能访问外部类的非静态的属性和方法。外部类不能访问内部类的非静态的属性和方法。
package com;
public class StaticInnerClass {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.innerShow();
Outer outer = new Outer();
outer.outerShow();
}
}
class Outer{
private String name = "张三";
private int age1 = 24;
private static int age2 = 200;
public void outerShow(){
System.out.println("外部类");
System.out.println(name);
System.out.println(age1);
System.out.println(Inner.age3);
System.out.println("------------------------------");
}
public static class Inner{
private String name = "李四";
private int age2 = 24;
private static int age3 = 300;
public void innerShow(){
System.out.println("静态内部类");
System.out.println(name);
System.out.println(age2);
/*静态内部类不能访问外部类的非静态成员*/
System.out.println(Outer.age2);
System.out.println("------------------------------");
}
}
}
五、匿名内部类
特点
1.匿名内部类是没有名称的内部类,没办法引用它们。必须在创建时,作为new语句的一部分来声明并创建它们的实例。
2.匿名内部类必须继承一个类(抽象的、非抽象的都可以)或者实现一个接口。如果父类 (或者父接口)是抽象类,则匿名内部类必须实现其所有抽象方法。
3.匿名内部类中可以定义代码块,用于实例的初始化,但是不能定义静态代码块。
语法
这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例。
new interface/superclass() { //类体}
import java.time.Period;
public class AnonymousInnerClass {
public static void main(String[] args) {
Person person = new Person();
person.feed(new Animal() {
@Override
public void eat() {
System.out.println("狗啃骨头");
}
});
new Animal() {
private String name = "火锅";
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void show(){
System.out.println("猫爱睡觉");
}
}.show();
/* person.feed(cat);*/
}
}
class Person{
public void feed(Animal animal){
animal.eat();
}
}
abstract class Animal{
public abstract void eat();
}
六、局部内部类
特点
1.定义在代码块、方法体内的类叫局部内部类。
2.局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”和“外部类名.this.方法名 (参数)”的形式。
3.对外部世界完全隐藏,只能在其作用域内生成对象。
限制
1.局部类不能加访问修饰符,因为它们不是类成员。
2.成员内部类不能与外部类重名。
3.局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰。
import java.io.OutputStream;
public class LocaInnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.outerShow();
}
}
class Outer{
private String name = "张三";
private int num1 = 10;
private static int num2 = 20;
public void outerShow(){
/*JDK1.8之后默认添加了final*/
int num3 = 30;
/*局部内布类不能添加访问修饰符*/
class Inner{
private int num4 = 40;
public void innerShow(){
System.out.println(num4);
System.out.println(Outer.this.num1);
System.out.println(Outer.num2);
System.out.println(num3);
}
}
Inner inner = new Inner();
inner.innerShow();
}
}