您的位置:首页 > 编程语言 > Java开发

Java基础加强重温_02:接口(成分:抽象方法、常量、默认方法、静态方法、私有方法,实现、继承)、final关键字(修饰类、方法)、单例设计模式(懒汉、饿汉)、枚举(底层原理、编译与反编译)

2020-03-25 18:52 1181 查看

一、接口

接口是更加彻底的抽象,接口成分仅有抽象方法、常量。(JDK1.8之前),接口同样是不能创建对象的。

从jdk1.9开始:接口中允许定义私有方法

定义格式

修饰符 interface 接口名称{
// 抽象方法
// 常量
}

1、接口成分

抽象方法

接口定义的方法全部都是抽象方法,会自动省略 public abstract

// 接口抽象方法
// public abstract void run();
void run();

常量

接口定义的变量是常量,会自动省略 public final static。也就是说在接口中定义的成员变量实际上是一个常量。使用public static final修饰后,变量值就不可被修改,并且是静态化的变量可以直接用接口名访问,所以也叫常量。常量必须要给初始值。常量命名规范建议字母全部大写,多个单词用下划线连接。

// public static final int AGE = 12 ;
int AGE  = 12;  //常量

// public static final String SCHOOL_NAME = "黑马程序员";
String SCHOOL_NAME = "黑马程序员"; // 字符串常量

2、接口的实现和继承

实现

类与接口的关系为实现关系,即类实现接口,实现使用 implements 关键字。 该类可以称为接口的实现类,也可以称为接口的子类。

Java中的类可以实现一个接口也可以同时实现多个接口,可以理解成实现多个规范,这是合理的。
实现的多个接口中的抽象方法全部需要重写,没有全部重写实现类也变成抽象类。

class 实现类 implements 接口1,接口2,...{

}

继承

接口和接口之间可以继承,可以继承一个,也可以继承多个。接口继承接口就是把其他接口的抽象方法与本接口进行了合并。

  • 1、提高代码的复用性
  • 2、提高代码的拓展性
interface 子接口 extends 父接口1,父接口2,...{

}

类与接口是实现关系
接口与接口是继承关系

3、JDK1.8以后接口新增特性

含有默认方法和静态方法(>=JDK1.8)

默认方法:
使用 default 修饰,不可省略,供子类调用或者子类重写(子类对象.默认方法)。
权限修饰符默认是 public(默认加上),可以被继承、被重写,但是不能像子类一样使用super调用。

静态方法:
使用 static 修饰,供接口直接调用(接口名.静态方法)。

  • 继承、实现都无法重写静态方法
  • 静态方法可以被继承,但是不能通过实现继承
    理解: 类1 extends 类2 implements 接口,类1能拿到类2的静态方法,但不能拿到接口的静态方法。
    接口1 extends 接口2,接口1可以拿到接口2的静态方法
public interface InterFaceName {
// 默认方法
public default void method() {
// 执行语句
}

// 静态方法
public static void method2() {
// 执行语句
}
}

重写默认方法注意(了解):

子接口重写默认方法时,default关键字可以保留。
实现类重写默认方法时,default关键字不可以保留。

含有私有方法和私有静态方法(>=JDK1.9)

私有方法: 使用 private 修饰,供接口中的默认方法或者静态方法调用。

  • 接口定义公开的默认方法和公开的静态方法调用接口的私有方法

定义格式

private [static] 返回值 方法名(参数...) {
}

代码示例:

public interface InterFaceName {
//私用方法
private void method() {
// 执行语句
}

//私有静态方法
private static void method() {
// 执行语句
}
}

普通方法和静态方法的调用:

  • 静态方法能调用静态方法
  • 普通方法能调用普通方法和静态方法

4、实现多个接口使用注意事项

接口多实现情况下调用各个接口的静态方法

  • 调用方式:各自的接口名.静态方法
  • 静态方法名一致也不影响,因为可以通过接口名区分

父类中的方法和接口中的默认方法重名问题

方法优先级,就近原则:本类 -> 父类 -> 接口

当多实现情况下,接口中有同名的default方法时,会报错(二义性)

二、final关键字

final是不可改变,最终的含义。可以用于修饰类、方法和变量(成员变量、静态成员变量、局部变量)。

  • 类:被修饰的类,不能被继承。
  • 方法:被修饰的方法,不能被重写。
  • 变量:被修饰的变量,有且仅能被赋值一次。(在定义变量的时候赋值)

1、修饰类

被final修饰的类无法被继承(太监类)

final class 类名 {
}

查询API发现像 public final class String 、 public final class Math 、 public final class Scanner等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。

2、修饰方法

final修饰的方法无法被子类重写。

修饰符 final 返回值类型 方法名(参数列表){
//方法体
}

代码:

class Fu2 {
//void(返回值)前面的修饰符可以随意调换顺序
final public void show1() {
System.out.println("Fu2 show1");
}

public void show2() {
System.out.println("Fu2 show2");
}
}

class Zi2 extends Fu2 {
// @Override
// public void show1() {
// System.out.println("Zi2 show1");
// }

@Override
public void show2() {
System.out.println("Zi2 show2");
}

3、修饰变量(局部变量、静态成员变量、成员变量)

局部变量

局部变量:在方法中定义的变量。
基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。

public class FinalDemo1 {
public static void main(String[] args) {
// 声明变量,使用final修饰
final int a;
// 第一次赋值
a = 10;
// 第二次赋值
a = 20; // 报错,不可重新赋值

// 声明变量,直接赋值,使用final修饰
final int b = 10;
// 第二次赋值
b = 20; // 报错,不可重新赋值
}
}

静态成员变量

static修饰的变量被final修饰称之为【常量】。
被final修饰的常量名称,一般都有书写规范,所有字母都大写。

class Video {
//等价静态的基本类型变量
//常量有一个命名规范:常量名一般用大写
//快捷键 :ctrl+shift+u,选择部分变大写
//直接通过类名.LEVEL调用,不需要经过构造方法,必须在声明的时候进行初始化

public static final  char LEVEL = 3;

}

实例成员变量

实例成员变量涉及到初始化的问题,初始化方式有显示初始化和构造器初始化,只能选择其中一个方式初始化

  • 显示初始化: 即在定义成员变量的时候立马赋值
public class Student {
final int num = 10;
}
  • 构造器初始化: 在构造方法中赋值一次。
    每个构造方法中(有参/无参)都要赋值一次
public class Student {
final int num = 10;
final int num2;

//在无参中赋值
public Student() {
this.num2 = 20;
//  this.num2 = 20;
}

//在有参中赋值
public Student(String name) {
this.num2 = 20;
//	this.num2 = 20;
}
}

三、单例设计模式

正常情况下一个类可以创建多个对象。单例设计模式,即一个类只有一个对象实例。
单例设计模式的概念/作用:使得JAVA程序的某个类在运行阶段只能创建一个对象。

实现步骤

现状:一个类可以创建无数个对象。改变为:一个类只能创建一个对象

  • 1、私有构造方法,把构造方法通过private隐藏起来
  • 2、定义私有静态成员变量存储单例
  • 3、通过公开的静态getter方法获取单例

单例设计模式的分类

1.饿汉式单例

饿汉单例设计模式就是使用类的时候已经将对象创建完毕,不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故被称为“饿汉模式”。

public class Singleton {
// 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
private Singleton() {}

// 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
private static final Singleton instance = new Singleton();

// 3.定义一个静态方法返回这个唯一对象。
public static Singleton getInstance() {
return instance;
}
}

2.懒汉式单例

懒汉单例设计模式就是调用getInstance()方法时实例才被创建,先不急着实例化出对象,等要用的时候才例化出对象。不着急,故称为“懒汉模式”。

public class Singleton {
// 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
private static Singleton instance;

// 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
private Singleton() {}

// 3.定义一个静态方法返回这个唯一对象。要用的时候才例化出对象
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}

3、双重锁形式(解决懒汉式的线程安全问题)

懒汉单例设计模式在多线程环境下可能会实例化出多个对象,不能保证单例的状态。我们在学习完多线程的时候还会再讲解如何解决这个问题。

饿汉式和懒汉式的区别

静态成员变量是声明的时候初始化,还是get的时候初始化

饿汉式还是懒汉式用的多呢?

饿汉式实现更简单,懒汉式其实有线程安全问题(学多线程的时候会学)。

四、多例设计模式(与单例设计模式对应)

1、多例设计模式

https://blog.csdn.net/qq_38737992/article/details/89644649

2、老王讲设计模式(四)——多例模式

https://www.jianshu.com/p/78061e1f79a5

五、枚举

枚举是一个特殊的类,有固定实例个数的类型,我们可以把枚举理解成有固定个数实例的多例模式。即枚举能用来表达固定的几个特定的选项。

枚举定义格式:

public enum 枚举名{
//第一行都是罗列枚举实例,这些枚举实例直接写大写名字即可。
选项1,选项2,....;
}

枚举的使用:

作为数据类型使用

枚举名.选项

1、不使用枚举存在的问题

假设我们要定义一个人类,人类中包含姓名和性别。通常会将性别定义成字符串类型,代码演示如下:

public class Person {
private String name;
private String sex;

public Person() {
}

public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
// 省略get/set/toString方法
}
public class Demo01 {
public static void main(String[] args) {
Person p1 = new Person("张三", "男");
Person p2 = new Person("张三", "abc"); // 因为性别是字符串,所以我们可以传入任意字符串
}
}

不使用枚举存在的问题:可以给性别传入任意的字符串,导致性别是非法的数据,不安全,违反代码的逻辑性。

2、枚举的作用与应用场景

枚举的作用:一个方法接收的参数是固定范围之内的时候,即可以穷举的固定几个选项,那么可使用枚举。
枚举的应用:枚举通常可以用于做信息的分类,如性别,方向,季度等。

入门案例

1、 定义枚举:BOY表示男,GIRL表示女

enum Sex {
BOY, GIRL; // 男,女
}

2、Perosn中的性别有String类型改为Sex枚举类型

public class Person {
private String name;
private Sex sex;
public Person() {
}

public Person(String name, Sex sex) {
this.name = name;
this.sex = sex;
}
// 省略get/set/toString方法
}

3.、使用是只能传入枚举中的固定值

public class Demo02 {
public static void main(String[] args) {
Person p1 = new Person("张三", Sex.BOY);
Person p2 = new Person("张三", Sex.GIRL);
Person p3 = new Person("张三", "abc");
}
}

测试运行。

入门案例枚举底层分析

枚举的本质是一个类,我们刚才定义的Sex枚举最终效果如下(通过编译-反编译后分析):

enum Sex {
BOY, GIRL; // 男,女
}
//1、枚举Sex是一个final clss 继承了Enum类
final class Sex extends Enum{

//2、枚举中的选项其实是枚举类的常量,用枚举类做数据类型,在静态代码块中初始化
public static final Sex BOY;
public static final Sex GIRL;

public static SEX[] values(){};
public static SEX valueOf(java.lang.String){};

//3、枚举中的构造方法是私有的,多例(单例)
private Sex(){

}

//初始化枚举选项
static {
BOY = new SEX();
GIRL =  new SEX();
};
}

因为枚举的本质是一个类,所以枚举中还可以有成员变量,成员方法等。

public enum Sex {
BOY(18), GIRL(16);

//成员变量
public int age;

// getter/setter方法
Sex(int age) {
this.age = age;
}

//成员方法
public void showAge() {
System.out.println("年龄是: " + age);
}
}

测试类

public class Demo03 {
public static void main(String[] args) {
Person p1 = new Person("张三", Sex.BOY);
Person p2 = new Person("张三", Sex.GIRL);
Sex.BOY.showAge();
Sex.GIRL.showAge();
}
}

编译和反编译研究枚举底层

枚举是一种特殊的类

编译:

  • java文件 -> javac编译 -> class文件

反编译工具:

  • class文件 -> 反编译工具 -> java文件

怎么找class文件:

  • 模块名右键->show in explorer -> out -> …->包名->class文件
  • 如果没有:要编译的类右键->recompile

反编译工具:

  • jd-gui、xjad:配合起来用

小结:

枚举的底层
1、枚举是一个final clss 继承了 Enum类
2、枚举中的选项其实是枚举类的常量,在静态代码块中初始化
3、枚举中的构造方法是私有的,多例(单例)。一个选项单例,多个选项多例
4、枚举也能定义方法、构造方法

枚举如果想携带额外信息(改造枚举类Sex):

  • 1、在枚举中定义新的成员变量
enum Sex {
BOY, GIRL; // 男,女

//如果想枚举额外添加更多的信息
//1、在枚举中定义新的成员变量
private String name;

}
  • 2、修改构造方法,把新的成员变量加入
enum Sex {
BOY, GIRL; // 男,女

//如果想枚举额外添加更多的信息
//1、在枚举中定义新的成员变量
private String name;

// 2、修改构造方法,把新的成员变量加入
private Direction(String name) {
this.name = name;
}

}

3、枚举中常量需要根据新的构造方法进行调整

enum Sex {
//3、枚举中常量需要根据新的构造方法进行调整,传入参数。
BOY("男"), GIRL("女"); // 男,女

//如果想枚举额外添加更多的信息
//1、在枚举中定义新的成员变量
private String name;

// 2、修改构造方法,把新的成员变量加入
private Direction(String name) {
this.name = name;
}

}

增加信息后反编译,初始化选项的static代码块

//初始化枚举选项
static {
BOY = new SEX("BOY","男");
GIRL = new SEX("GIRL","女");
};

理解:即定义新的变量,是给选项定义的。选项要传入这个参数。static代码块初始化后选项会携带这个参数。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
MrWuMC 发布了11 篇原创文章 · 获赞 1 · 访问量 269 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐