/*
- 类成员结构之内部类的使用
- 1,Java中可以在一个类A中定义一个类B,类A为外部类,类B为内部类,
- 注意内部类B的类名不能与外部类A重名
- 成员内部类编译以后生成 外部类名$内部类名.class字节码文件
- 局部内部类编译以后生成 外部类名$ 数字 内部类名.class字节码文件(加数字为了防止重名)
- 2,内部类按照声明的位置分为:
- 成员内部类(静态的与非静态的)
- 1,作为外部类的成员
-
可以调用外部类的结构
-
不同于外部类不能被static修饰,内部类可以声明为static的。
-
不同于外部类只能用public或缺省权限,内部类可以使用private和protected修饰
- 2,作为一个类
-
类内可以有属性,方法,构造器,代码块,内部类
-
类可以被继承,也可以用final修饰,声明不能被继承
-
内部类可以是抽象类,可以被abstract修饰
- 3,成员内部类的使用:
- 3.1创建成员内部类的变量
- 静态内部类对象:外部类名.内部类名 变量名 = new 外部类名.内部类名();
- 非静态内部类对象:需要使用外部类的实例化对象调用创建 外部类名.内部类名 变量名 = 外部实例对象名.new 内部类名();
- 3.2成员内部类调用外部类结构
-
调用同名同参方法:
- 外部类名.this.方法名();
- this.方法名();
- 没有同名方法时直接使用 方法名();的方式就可以自动识别
-
调用同名属性:
- 外部类名.this.属性名();
- this.属性名();
- 没有同名方法时直接使用 属性名 的方式就可以自动识别。
- 3.3成员内部类使用注意
-
非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员。(从成员生命周期角度考虑,需要一致)
-
外部类访问成员内部类的成员,需要“内部类.成员”(静态内部类)或“内部类对象.成员”(非静态内部类)的方式
-
成员内部类可以直接使用外部类的所有成员,包括私有的数据
-
当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的(内部类作为外部类的一个结构,与属性方法类似,需要是静态的才能被外部类的静态方法调用)
- 总结:成员内部类相比外部类可以使用的权限修饰符多了两个,可以声明为静态的,限制为静态内部类不能有非静态结构。
- 4,局部内部类(定义在构造器,方法体,代码块中,先声明后使用。除此之外的任何地方都不能使用该类)
- 4.1局部内部类的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类的父类或父接口类型
- 4.2局部内部类可以使用外部类的成员,包括私有的。
- 4.3局部内部类和局部变量地位类似,不能使用public,protected,缺省,private
- 4.4局部内部类不能使用static修饰,因此也不能包含静态成员
- 4.5局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局部变量的生命周期不同所致。
- 4.6局部内部类可以声明为final和abstract的
- 总结:局部内部类很少用,限制比成员内部类多。通常用在实现一个接口上。内部只需要重写接口的抽象方法。
- 5,匿名内部类
- 5.1匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
- 5.2匿名内部类必须继承父类或实现接口
- 5.3匿名内部类只能有一个对象,对象只能使用多态形式引用
- 5.4匿名内部类的使用格式与父类类和接口的匿名类的使用方法相同。
*/
package object_chapter2;
public class Object_InnerClass {
static int number = 10;
int arguments = 20;
public static void main(String[] args) {
//创建静态成员内部类对象
Vehicle.Engine e = new Vehicle.Engine();
System.out.println("发动机有" + e.cylinderNumber + "个汽缸");
new Vehicle.Engine().work();
//创建非静态成员内部类对象
Vehicle v = new Vehicle();
Vehicle.Room r = v.new Room();//或者v.new Vehicle.Room()
System.out.println("车里有" + r.chair + "个座位");
r.reName("车名:五菱之光");
new Vehicle().new Room().set();
v.getInstance().compare(v);
}
public static void method() {
int num = 11;
//方法体内的局部内部类
class InnerClass{
void show() {
// num = 12;
System.out.println(num);//局部内部类的方法中可以调用内部类所在方法的局部变量。不能修改
//在JDK1.7及以前,局部变量想要被局部内部类调用必须显式的被声明为final类型的,JDK1.8后会自动识别为final的。
//由于局部内部李生成的字节码文件是独立的,外部类中的变量想要被内部类使用只能是常量,内部类使用的是外部类变量的副本
//只能使用,无法修改。
}
}
// num++;//final的变量不能修改,否则局部内部类调用时会报错。
}
public Object_InnerClass() {
//构造器中定义的局部内部类
class InnerClass{
}
}
{
//代码块中定义的局部内部类
class InnerClass{
}
}
//静态内部类
private static final class InnerClass1{
void method() {
number = 110;
// Object_InnerClass.this.arguments = 20;//静态内部类中无法调用非静态结构
}
}
//非静态内部类
protected class InnerClass2{
void method() {
Object_InnerClass.number = 110;
Object_InnerClass.this.arguments = 20;//非静态内部类中可以调用非静态结构
}
}
class InternalClass{
//内部类中也可以嵌套一个内部类
class InnerInternalClass{
}
}
}
class Vehicle{
static int wheelNumber = 4;
String name = "号称秋名山之神";
void run() {
System.out.println("可以在各种路况上跑");
}
//静态成员内部类
static class Engine{
int cylinderNumber = 4;
void work() {
System.out.println("输出200匹马力的动力");
}
}
//非静态成员内部类
class Room{
//static int chair = 4;//非静态内部类不允许使用静态结构
int chair = 7;
String name = "内部空间极大";
void set() {
Vehicle.this.run();//内部类可以调取外部类的结构
carry();//不重名的情况下可以省略前面的部分
System.out.println("可以坐很多个人");
}
void reName(String name) {
System.out.println(name);//调用方法形参
System.out.println(this.name);//调用内部类属性
System.out.println(Vehicle.this.name);//调用外部类同名属性
}
}
void carry() {
System.out.println("能拉人能载货");
}
//局部内部类的常见场景,方法返回值是一个接口或者抽象类
Comparable getInstance() {
//创建一个内部类为借口的实现类
class MyCompareable implements Comparable{
@Override
public void compare(Vehicle v) {
System.out.println("不管什么车都挡不住五菱的光辉!!");
}
}
//返回内部类的实例
// return new MyCompareable();
//方式二,使用匿名内部类
return new Comparable() {
@Override
public void compare(Vehicle v) {
System.out.println("天下无敌");
}
};
}
}
interface Comparable{
void compare(Vehicle v);
}