一,抽象类
抽象类为用abstract修饰的类
1,定义的成员变量与普通的类没有区别
2,抽象类不可以被实例化
3,当一个类不具体描述某个对象时,可以定义为抽象类
4,如果一个类包含抽象方法,则这个类必须是抽象类,没有抽象方法,也可以被称为抽象类
5,一个方法可以被修饰为abstract,这个方法可以不被实现,被称为抽象方法
例如:public abstract void draw();
6,抽象类也可以发生向上转型,动态绑定,多态
7,抽象方法,满足重写特点,(一定要被子类重写)被static,final,private、修饰都是不能发生重写的
@Override public void draw() { System.out.println("画一个矩形"); } }//对draw()方法的重写
8,当一个普通类A,继承了一个抽象方法,但不想重写抽象类的方法,可以把A改为一个抽象类,但如果A被B继承,则B这个类要重写所有的抽象方法
二,接口
1,接口用interface来定义
2,接口中的成员变量默认被public static final修饰,且接口中的成员变量必须要初始化。所以有以下两种写法:
法一:public static final int age1=10; 法二:int age1=10;
3,接口的方法,默认被public abstract修饰,故为抽象方法,不能有具体的实现,一般直接写为void draw();
4,接口为引用类型,所以不能被实例化为对象
5,接口中定义的方法能具体的实现的有两种:第一种为default修饰的方法,第二种为静态方法
void text1(); public static void text2 (){ System.out.println("静态方法"); } public default void text3(){ System.out.println("default方法"); }//接口中的方法 @Override public void text1() { System.out.println("重写text1"); } @Override public void text3() { System.out.println("重写default");//在实现接口的类中,对接口方法进行重写
我们可以通过实例化,用对象的引用来访问重写的text1和text3,也可以用接口名访问访问接口中的静态方法<A.text2();>。default修饰的方法并不是必须要重写的。
6,使用接口时,用关键字implements来实现。例如:class A implements IB{}
7,当一个类实现了这个接口,就要对接口中的方法进行重写(因为接口中的方法为抽象方法)
8,一个类可以实现多个接口,但这个类一定要重写以上接口中的全部抽象方法。例如:
interface IA{ void textA(); } interface IB{ void textB(); } class Demo2 implements IA ,IB{ @Override public void textA() { System.out.println("textA"); } @Override public void textB() { System.out.println("textB"); } }
9,接口可以继承多个接口,用关键字extends来实现。例如:interface IA{};interfaceI B{};interface IC extends IA,IB{};而实现接口IC的这个类中,一定要重写IA,IB,IC中的所有抽象方法。
接口的初步练习:
public interface IUSB { void openDevice(); void closeDevice(); }--------------------------
public class KeyBoard implements IUSB{ @Override public void openDevice() { System.out.println("打开键盘"); } @Override public void closeDevice() { System.out.println("关闭键盘"); } public void input(){ System.out.println("键盘输入"); } }----------------------------------------
public class Mouse implements IUSB{ @Override public void openDevice() { System.out.println("打开鼠标"); } @Override public void closeDevice() { System.out.println("关闭鼠标"); } public void click(){ System.out.println("点击鼠标"); } }--------------------------------------------
public class Computer { public void powerOff(){ System.out.println("关闭电脑"); } public void powerOn(){ System.out.println("打开电脑"); } public void useDevice(IUSB usb){ usb.openDevice(); if (usb instanceof Mouse){ Mouse mouse=(Mouse)usb; mouse.click(); } if(usb instanceof KeyBoard){ KeyBoard keyBoard=(KeyBoard) usb; keyBoard.input(); } usb.closeDevice(); } public static void main(String[] args) { Computer computer=new Computer(); computer.powerOn(); computer.useDevice(new KeyBoard()); computer.useDevice(new Mouse()); computer.powerOff(); } }
10,一个类可以同时继承抽象类和实现多个接口:
public abstract class Animal { protected String name; protected int age; public Animal(String name, int age) { this.name = name; this.age = age; } public abstract void eat(); }//抽象类
public interface IFly { void fly(); }//第一个接口
public interface IRunning { void run(); }//第二个接口
public interface ISwamming { void swam(); }//第三个接口
public class Duck extends Animal implements ISwamming,IFly,IRunning{ public Duck(String name, int age) { super(name, age); } @Override public void eat() { System.out.println(this.name+"吃鸭粮"); } @Override public void fly() { System.out.println(this.name+"飞..."); } @Override public void run() { System.out.println(this.name+"跑..."); } @Override public void swam() { System.out.println(this.name+"游泳..."); } }
public static void eatfunc(Animal animal){ animal.eat(); } public static void runfunc(IRunning running){ running.run(); } eatfunc(new Fish("小鱼",3));
11, 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
12,接口的实例:
想要比较对象中的成员变量的数值大小,因为它为引用数据类型,所以不能直接比较,此时需要一个接口,来实现比较,这个接口为Comparable<T>。
class Student implements Comparable<Student>{ String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; }
@Override public int compareTo(Student o) { if(this.name.compareTo(o.name)>0){ return 1; } else if (this.name.compareTo(o.name)==0) { return 0; }else { return -1; }//对方法的重写(姓名的比较) } @Override public int compareTo(Student o) { if(this.age>o.age){ return 1; }else if(this.age==o.age){ return 0; }else{ return -1; } }//对方法的重写(年龄的比较) }
public static void main1(String[] args) { Student student1=new Student("zhangsan",12); Student student2=new Student("lisi",10); if(student1.compareTo(student2)>0){ System.out.println("student1>student2"); }else{ System.out.println("student1<=student2"); } } -------------------------------------------------
public static void mysort(Comparable[] comparable){ for(int i=0;i<comparable.length-1;i++){ for (int j=0;j<comparable.length-1-i;j++){ if(comparable[j].compareTo(comparable[j+1])>0){ Comparable tmp=comparable [j]; comparable[j]=comparable[j+1]; comparable[j+1]=tmp; } } } }
public static void main(String[] args) { Student[]students=new Student[3]; students[0]=new Student("zhangsan",12); students[1]=new Student("lisi",8); students[2]=new Student("wamgwu",10); System.out.println(Arrays.toString(students)); //Arrays.sort(students); mysort(students); System.out.println(Arrays.toString(students)); }在 Arrays.sort();方法中会自动调用 compareTo 方法(所以在用sort比较时,也需要实现Comparable<T>接口). compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象. 然后比较当前对象和参数对象的大小关系.
(1)在接口Comparable<T>中有一个方法compareTo,需要对这个方法进行重写。
(2)Comparable接口有局限性,一旦写死了比较方式,后期就不能随意更改了
(3) 自己实现比较代码时,mysort(students);中的students,使用接口来接收的,所以自己实现比较代码时,也需要实现接口Comparable<T>,下图为Student类没有实现接口所报出的错误
也可以使用 Comparator<T>来实现比较。
public class Agecomparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.age- o2.age; } }//年龄比较器
public class Namecomparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name); } }//名字比较器
public static void main1(String[] args) { Student student1=new Student("zhangsan",9); Student student2=new Student("lisi",10); Agecomparator agecomparator=new Agecomparator(); int ret=agecomparator.compare(student1,student2); System.out.println(ret); Namecomparator namecomparator=new Namecomparator(); int ret2=namecomparator.compare(student1,student2); System.out.println(ret2); } -------------------------------------------------------
public static void main(String[] args) { Student[]students=new Student[3]; students[0]=new Student("zhangsan",12); students[1]=new Student("lisi",8); students[2]=new Student("wamgwu",10); Namecomparator namecomparator=new Namecomparator(); System.out.println(Arrays.toString(students)); Arrays.sort(students,namecomparator); System.out.println(Arrays.toString(students)); }//调用namecomparator来比较students。
13,深拷贝
class Student implements Cloneable{ 必须实现cloneable接口(空接口、标记接口),只要实现这个克隆接口,证明这个类才能被实现clone int age; public Student(int age) { this.age = age; } @Override public String toString() { return "Student{" + "age=" + age + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } 所有的类都继承object,因为object父类下面的方法为protected clone,父类,子类的包不同,不能直接访问,需要用到super } public class Text { public static void main(String[] args) throws CloneNotSupportedException{ Student student1=new Student(10);异常问题 Student student2=(Student) student1.clone(); 为向下转型,所以要强制类型转换 } } -------------------------------------------------------------------------
class Money implements Cloneable{ double money=12.5; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Student implements Cloneable{ int age; Money m=new Money(); public Student(int age) { this.age = age; } @Override public String toString() { return "Student{" + "age=" + age + '}'; } @Override protected Object clone() throws CloneNotSupportedException { Student tmp=(Student) super.clone(); tmp.m=(Money) this.m.clone(); return tmp; } } public class Text { public static void main(String[] args) throws CloneNotSupportedException{ Student student1=new Student(10); Student student2=(Student) student1.clone(); System.out.println(student1.m.money); System.out.println(student2.m.money); System.out.println("--------------"); student2.m.money=100; System.out.println(student1.m.money); System.out.println(student2.m.money); } }
浅拷贝:
浅拷贝克隆出的student2跟student1里面的数据一模一样,所以两者中的m都指向同一块空间(m为引用类型,存储的为地址)
深拷贝:
三,抽象类与接口的区别
核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中 不能包含普通方法, 子类必须重写所有的抽象方法
四,Object类
Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父 类。即所有类的对象都可以使用Object的引用进行接收。
class Person{ String name; int age; public Person(String name, int age) { this.name = name; this.age = age; }
@Override public boolean equals(Object obj) { Person person=(Person) obj; if(this.name.equals(person.name)){ return true; }else return false; }//重写实现想要实现的功能
public static void main(String[] args) { Person person1=new Person("zhangsan",10); Person person2=new Person("zhangsan",9); System.out.println(person1.equals(person2));
}
因为person1和person2为引用类型,比较的地址,并不能实现想实现的功能,所以需要重写equals
hashcode方法(算出具体对象的位置):
Person person1=new Person("zhangsan",10); Person person2=new Person("zhangsan",10); System.out.println(person1.hashCode()); System.out.println(person2.hashCode());
此时输出的为两个不同的地址;
从代码上看,是两个不同的对象,但从逻辑上来说,名字,年龄一样,就是同一个人,所以想要这两个对象放到同一个位置,也就是想要两个哈希值是同样的,所以需要重写hashcode方法
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
以后只要是自定义类型,一定要重写hashcode方法和equals方法。
标签:JAVA,void,System,接口,age,详解,Student,println,public From: https://blog.csdn.net/2302_81705247/article/details/137022599