[ java基础 ] 内部类.类/实例的初始化

内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,不在其他地方单独使用,那么整个内部的完整结构最好使用内部类。

根据内部类声明的位置(如同变量的分类),我们可以分为:
(1)成员内部类:
静态成员内部类
非静态成员内部类
(2)局部内部类
有名字的局部内部类
匿名的内部类

  • 非静态成员内部类

和外部类一样,它只是定义在外部类中的另一个完整的类结构
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关

可以在非静态内部类中声明属性、方法、构造器等结构,但是不允许声明静态成员,但是可以
继承父类的静态成员,而且可以声明静态常量。
可以使用abstract修饰,因此它也可以被其他类继承
可以使用final修饰,表示不能被继承
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。
和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private(推荐)
外部类只允许public或缺省的
还可以在非静态内部类中使用外部类的所有成员,哪怕是私有的
在外部类的静态成员中不可以使用非静态内部类哦
就如同静态方法中不能访问本类的非静态成员变量和非静态方法一样
在外部类的外面必须通过外部类的对象才能创建非静态内部类的对象
因此在非静态内部类的方法中有__两个this对象__,一个是外部类的this对象,一个是内部类的
this对象

  • 静态内部类

静态内部类的特点:
和外部类一样,它只是定义在外部类中的另一个完整的类结构
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
可以在静态内部类中声明属性、方法、构造器等结构,包括静态成员
可以使用abstract修饰,因此它也可以被其他类继承
可以使用final修饰,表示不能被继承
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。
和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private(推荐)
外部类只允许public和缺省
只可以在静态内部类中使用外部类的静态成员,哪怕是私有的
在静态内部类中不能使用外部类的非静态成员哦
在外部类的外面不需要通过外部类的对象就可以创建静态内部类的对象

*其实严格的讲(在James Gosling等人编著的《The Java Language Specification》)静态内部类
不是内部类,而是类似于C++的嵌套类的概念,外部类仅仅是静态内部类的一种命名空间的限定名
形式而已。所以接口中的内部类通常都不叫内部类,因为接口中的内部成员都是隐式是静态的。例
如:Map.Entry。

  • 局部内部类

和外部类一样,它只是定义在外部类的某个方法中的另一个完整的类结构
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无

可以在局部内部类中声明属性、方法、构造器等结构,但不包括静态成员,除非是从父类继承
的或静态常量
可以使用abstract修饰,因此它也可以被同一个方法的在它后面的其他内部类继承
可以使用final修饰,表示不能被继承
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名、$符号、编号。
这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类
和成员内部类不同的是,它前面不能有权限修饰符等
局部内部类如同局部变量一样,有作用域
局部内部类中使用能访问外部类的静态还是非静态的成员,取决于所在的方法
局部内部类中还可以使用所在方法的局部常量,即用final声明的局部变量
JDK1.8之后,如果某个局部变量在局部内部类中被使用了,自动加final

  • 匿名内部类

其实匿名内部类是一种特色的局部内部类,只不过没有名称而已。因此
在匿名内部类中要访问访问外部类的静态还是非静态的成员,取决于所在的方法;
匿名内部类中还可以使用所在方法的局部常量,即用final声明的局部变量
JDK1.8之后,如果某个局部变量在局部内部类中被使用了,自动加final
匿名内部类 :是接口实现的一种简化写法。它的__本质是一个 带具体实现的 父类或者父接口的 匿名
的 子类对象__。
开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步
操作,

  1. 定义子类
  2. 重写接口中的方法
  3. 创建子类对象
  4. 调用重写后的方法
    我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是
    做这样的快捷方式。

前提
匿名内部类必须继承一个父类或者实现一个父接口。

通常在方法的__形式参数是接口或者抽象类__时,也可以将__匿名内部类作为参数传递__。

a创建匿名内部类,并调用:

//接口
public abstract class FlyAble{
  public abstract void fly();
}
//创建匿名内部类,并调用:
public class InnerDemo {
  public static void main(String[] args) {
    /*
    1.等号右边:是匿名内部类,定义并创建该接口的子类对象
    2.等号左边:是多态赋值,接口类型引用指向子类对象
    */
    FlyAble  f = new FlyAble(){
      public void fly() {
        System.out.println("我飞了~~~");
     }
   };
    //调用 fly方法,执行重写后的方法
    f.fly();
 }
}

b通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。代码如下:

public class InnerDemo2 {
  public static void main(String[] args) {
       /*
    1.等号右边:定义并创建该接口的子类对象
    2.等号左边:是多态,接口类型引用指向子类对象
   */
    FlyAble  f = new FlyAble(){
      public void fly() {
        System.out.println("我飞了~~~");
     }
   };
    // 将f传递给showFly方法中
    showFly(f);
 }
  public static void showFly(FlyAble f) {
    f.fly();
 }
}

以上两步,也可以简化为一步,代码如下:

public class InnerDemo3 {
  public static void main(String[] args) {   
    /*
   创建匿名内部类,直接传递给showFly(FlyAble f)
    */
    showFly( new FlyAble(){
      public void fly() {
        System.out.println("我飞了~~~");
     }
   });
 }
  public static void showFly(FlyAble f) {
    f.fly();
 }
}

类和实例的初始化

  • 类初始化

(1)静态类成员变量的显式赋值语句
(2)静态代码块中的语句
整个类初始化只会进行一次,如果子类初始化时,发现父类没有初始化,那么会先初始化父类。

实例初始化

实例初始化方法的方法体,由四部分构成:
(1)super()或super(实参列表) 这里选择哪个,看原来构造器首行是哪句,没写,默认就是super()
(2)非静态实例变量的显示赋值语句
(3)非静态代码块
(4)对应构造器中的代码
特别说明:其中(2)和(3)是按顺序合并的,(1)一定在最前面(4)一定在最后面

执行特点:
创建对象时,才会执行
调用哪个构造器,就是指定它对应的实例初始化方法

创建子类对象时,父类对应的实例初始化会被先执行,执行父类哪个实例初始化方法,看用super()
还是super(实参列表)

*//子类重写getNumber()方法,那么创建子类的对象,就是调用子类的
getNumber()方法,因为当前对象this是子类的对象。

类初始化与实例初始化

结论
类初始化肯定优先于实例初始化。
类初始化只做一次。
实例初始化是每次创建对象都要进行。

枚举类

JDK 1.5之前需要自定义枚举类
枚举本质上就是一个类,它里面只有一组限定的对象!
比如:性别、三原色、星期等

自定义枚举类
构造器私有化
本类内部创建一组对象
添加public static修饰符,对外暴露该对象

通过关键字enum创建枚举类(JDK5.0)

枚举类的__注意事项__:

如果枚举类没有任何的构造器时,JVM自动给其提供一个私有无参的构造器;一旦有任何构造器,JVM不在提供
枚举类中的构造器的访问权限只能是private,不能是其他的访问权限,即使访问权限不写(缺省),JVM自动补上private
枚举类中对象名的这一行必须放在类中的第一行,对象名前面有其他的代码,编译报错
如果枚举类中的对象是通过无参构造器进行对象的创建,对象名后面的()可以省略不写
枚举类的中的对象被public static final进行修饰
枚举类都默认隐式继承Enum类,无法继承其他类,但可以实现接口
程序中的其他类也不能继承枚举类

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值