你好陌生人,请不要试图越过权限文章,谢谢!

20220830-0920-技术学习-java-02

接口(interface)

思考为什么接口不设计成抽象类?

  使用抽象类每个类只能被扩展一次,假设实现类已经继承了某一个抽象类,则它就不能继续拓展其他类。

1
2
3
4
5
6
7
8
9
10
abstract class Comparable {

}
class People {
}

class Employee extends Comparable,People {

}
// 此无法多拓展,报错

  接口则可以被实现多个,java设计过程中不允许多重继承,原因在于多重继承会让代码变得特别复杂。

1
2
3
4
5
6
public interface class People {
}
public interface class Comparable {
}
public class Employee implements People,Comparable {
}

静态和私有方法

  接口允许含有静态方法,私有方法一般为接口自身使用,用法很有限,只能作为接口中其他方法中的辅助方法(辅助啥)。

默认方法

  接口可以提供默认方法修饰(default),不过一般接口会被其他类实现,则默认方法一般来说会被覆盖。

接口与回调

  回调是一种常见的程序设计模式,在这种模式中,可以指定某个特定事件发生时应该采取的动作。如Timer类中,你可以构建一个定时器,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.jianfreespace;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;

public class TimePrinter implements ActionListener {

@Override
public void actionPerformed(ActionEvent event) {
System.out.println("At the tone,the time is"
+ Instant.ofEpochMilli(event.getWhen()));
Toolkit.getDefaultToolkit().beep();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.jianfreespace;


import javax.swing.*;

public class StartMain {


public static void main(String[] args) {

var listener = new TimePrinter();
Timer t = new Timer(1000,listener);
t.start();
JOptionPane.showMessageDialog(null,"Quit program?");

}




}

基于此代码会每一秒回调执行函数打印此语句,如图:

深拷贝与浅拷贝

  java中深浅拷贝的概念属于需要了解的内容,java中的传递都是值传递,但如果你需要克隆一个对象时候,其默认的都是浅克隆。并且clone方法是protection,如果你需要克隆一个对象,需要先重写clone方法。值得一提的是,clone方法是作为Object基类的方法,那么可以确定的是,任意一个类都是默认继承了Object,事实上作为一个超类存在的,所以我们的对象都是有一个clone对象。我们重写的clone其实也就是重写Object的Clone。如果需要重写,那么需要类实现Cloneable接口。介绍说Cloneable是作为一个 标记接口存在的。标记接口的唯一作用是运行类型在检查时使用instanceof。若你不实现这个接口类型,则编译器会报CloneNotSupportException的错误。

  而clone默认是浅拷贝,这里写了一个例子,首先我定义了几个类为People、Employee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.jianfreespace;

public class People {

String name;
int age;

People(String name,int age)
{
this.name = name;
this.age = age;
}


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return getClass().getName()
+ "[name=" + name
+ ",age=" + age
+"]";
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.jianfreespace;

import java.util.Date;

public class Employee implements Cloneable{

private String name;
private Double salary;
private Date hireDay;
private People people;

Employee(String name, Double salary) {
this.name = name;
this.salary = salary;
this.hireDay = new Date();

}

public People getPeople() {
return people;
}

public void setPeople(People people) {
this.people = people;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getSalary() {
return salary;
}

public void setSalary(Double salary) {
this.salary = salary;
}

public Date getHireDay() {
return hireDay;
}

public void setHireDay(Date hireDay) {
this.hireDay = hireDay;
}

@Override
public Employee clone() throws CloneNotSupportedException {

return (Employee) super.clone();
}
}

  这里我使用Employee引用了People对象,然后实现了clone方法。然后测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.jianfreespace;



public class StartMain {


public static void main(String[] args) throws CloneNotSupportedException, InterruptedException {

Employee employee = new Employee("Jianfreespace",20000.0);
employee.setPeople(new People("jian",23));
System.out.println("emplyee");
System.out.println(employee.getHireDay());
System.out.println(employee.getName());
System.out.println(employee.getSalary());
System.out.println(employee.getPeople());
Thread.sleep(3000);
Employee employeeClone = employee.clone();
employeeClone.setSalary(30000.0);
employeeClone.setName("hansJian");
employeeClone.getPeople().setAge(24);
System.out.println("clone");
System.out.println(employeeClone.getHireDay());
System.out.println(employeeClone.getName());
System.out.println(employeeClone.getSalary());
System.out.println(employeeClone.getPeople());

System.out.println("emplyee");
System.out.println(employee.getHireDay());
System.out.println(employee.getName());
System.out.println(employee.getSalary());
System.out.println(employee.getPeople());

}




}




emplyee
Thu Sep 01 17:06:52 CST 2022
Jianfreespace
20000.0
com.jianfreespace.People[name=jian,age=23]
clone
Thu Sep 01 17:06:52 CST 2022
hansJian
30000.0
com.jianfreespace.People[name=jian,age=24]
emplyee
Thu Sep 01 17:06:52 CST 2022
Jianfreespace
20000.0
com.jianfreespace.People[name=jian,age=24]



  结果就是,当我改变了people中的age时候,因为浅拷贝的原因,当你修改克隆对象中的people.age时,会改变原对象的值,这是因为clone是浅克隆,他们两个实际上引用的people是同一个对象,没有进行深层拷贝。这是存在的问题所在。若要进行深层拷贝,则需要重新clone方法时,克隆引用对象,即:

1
2
3
4
5
6
@Override
public Employee clone() throws CloneNotSupportedException {
Employee employee = (Employee) super.clone();
employee.people = (People) people.clone();
return employee;
}

emplyee
Thu Sep 01 17:44:26 CST 2022
Jianfreespace
20000.0
com.jianfreespace.People[name=jian,age=23]
clone
Thu Sep 01 17:44:26 CST 2022
hansJian
30000.0
com.jianfreespace.People[name=jian,age=24]
emplyee
Thu Sep 01 17:44:26 CST 2022
Jianfreespace
20000.0
com.jianfreespace.People[name=jian,age=23]



  这样就完成了一次深拷贝的全部过程。