接口:
接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。
1.使用关键字interface定义接口。
2. 接口不能被实例化。
一般一个接口定义在一个单独文件中。
接口当中的成员默认是public static finial的
所以定义时必须初始化。
接口里面的方法不能有具体的实现。
接口里面的方法默认是public abstract。
如果要实现可以在前面加default。
接口当中不能有构造方法。
接口需要被类实现使用关键字implements
package test2;
interface Wo{
void draw();
default void func(){
System.out.println("hh");
}
}
class Rect2 implements Wo{
@Override
public void draw() {
}
@Override
public void func() {
Wo.super.func();
}
}
public interface Testdemo1 {
public static void main(String[] args) {
}
}
1. 创建接口时 , 接口的命名一般以大写字母 I 开头 .2. 接口的命名一般使用 " 形容词 " 词性的单词 .3.接口中的方法和属性不要加任何修饰符号 , 保持代码的简洁性
接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法。
子类和父类之间是extends 继承关系,类与接口之间是 implements 实现关系。
看个例子。
结果
子类重写接口方法时不能使用默认的访问权限,因为子类默认权限是包权限,小于public,使用会报错。
接口中不能有静态代码块和构造方法 。
接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class。
如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类 。
为解决java不能多继承的问题,我们可以使用接口替代。
不能先实现接口,后继承类。
可以实现多个接口。
下面这个cc接口代表它不仅有funcc方法功能,还有A和B接口的功能。
此时仅仅重写funcc会报错。
下面看个例子。
package test3;
import java.util.Arrays;
class Score implements Comparable<Score>{
private int age;
private String name;
private int score;
Score(){
}
public Score(int a,String b,int c)
{
age=a;
name=b;
score=c;
}
@Override
public String toString() {
return "Score{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
public int compareTo(Score o)
{
if(this.age>o.age)
return 1;
else if(this.age<o.age)
return -1;
else
return 0;
}
}
public class Student {
public static void sort(Score s[])
{
for(int i=0;i<s.length;i++)
{
int exchange=1;
for(int j=0;j<s.length-i-1;j++)
{
if(s[j].compareTo(s[j+1])==1)
{
Score t=s[j];
s[j]=s[j+1];
s[j+1]=t;
exchange=0;
}
}
if(exchange==1)
break;
}
}
public static void main(String[] args) {
Score scores[]=new Score[3];
scores[0]=new Score(23,"wang",89);
scores[1]=new Score(21,"zhang",91);
scores[2]=new Score(30,"mi",86);
sort(scores);
System.out.println(scores[0]);
Arrays.sort(scores);
System.out.println(Arrays.toString(scores));
}
}
增加下面代码后。
class NameComparator implements Comparator<Score>{
@Override
public int compare(Score o1, Score o2) {
return o1.name.compareTo(o2.name);
}
}
这是一个比较器。
- 克隆
克隆点进去后发现实现是空的。这个是空接口也叫标记接口,作用是表示当前对象是可以被克隆的。
要克隆的类中像下面这样写。
我们使用克隆后发现报错。
因为这里面抛了个克隆异常。这个异常是编译时期的。
编译时期的异常可以采用在main后加同样的异常来解决。
而因为克隆返回的是父类,所以赋给score1后发生向下转型,所以又报错了。
可以通过强转解决。
上面意味着我们可以对自定义类型进行拷贝了。
下面看个例子。
package test4;
class Money{
public int money=12;
}
class Student implements Cloneable{
public Money m=new Money();
public String name;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Student{" +
"m=" + m +
", name='" + name + '\'' +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Student student1=new Student();
System.out.println(student1.m.money);
Student student2=(Student)student1.clone();
student2.m.money=2;
System.out.println(student1.m.money);
System.out.println(student2.m.money);
}
}
我们发现更改克隆出来的student2中m的money值,student1中的也会变。
其实这个是浅拷贝。
下面这样改就能对money进行深拷贝了。
package test4;
class Money implements Cloneable{
public int money=12;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable{
public Money m=new Money();
public String name;
@Override
protected Object clone() throws CloneNotSupportedException {
Student student=(Student)super.clone();
student.m=(Money) this.m.clone();
return student;
}
@Override
public String toString() {
return "Student{" +
"m=" + m +
", name='" + name + '\'' +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Student student1=new Student();
System.out.println(student1.m.money);
Student student2=(Student)student1.clone();
student2.m.money=2;
System.out.println(student1.m.money);
System.out.println(student2.m.money);
}
}
抽象类和接口
- Object类
hascode用来算对象位置。
而我们进行下面的改变后,结果就一样了。