如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
被abstract修饰的类就称为抽象类,不是一个具体的类
//抽象类
abstract class Shape {
public abstract void draw();//抽象方法
}
public class Text {
}
(1)抽象类不能进行实例化,也就是new一个抽象类
abstract class Shape {
public abstract void draw();//抽象方法
}
public class TextDame {
public static void main(String[] args) {
//Shape shape = new Shape();//报错,抽象类不能进行实例化
}
}
(2)抽象类中也可以包含普通的数据成员、方法、构造方法等
//抽象类
abstract class Shape {
public int a;//数据成员
public static int b;
//普通的方法
public void func(){
System.out.println("抽象方法中的普通方法");
}
//构造方法
public Shape(int a) {
this.a = a;
}
public abstract void draw();//抽象方法
}
public class Text {
}
(3)如果一个普通类A继承了一个抽象类B,那么这个普通类A需要重写抽象类B中所有的抽象方法
//抽象类
abstract class Shape {
public abstract void draw();//抽象方法
}
//普通类继承抽象类
class Cycle extends Shape {
// 必须重写抽象方法
@Override
public void draw() {
System.out.println("画○");
}
}
public class Text {
}
(4)如果一个抽象类C继承了一个抽象类B,那么这个抽象类C需要不用重写抽象类B中的抽象方法
//抽象类
abstract class Shape {
public abstract void draw();//抽象方法
}
//抽象类继承抽象类
abstract class Rect extends Shape {
// 不需要重写抽象方法
}
public class Text {
}
(5)在(4)的基础上,如果一个普通类D继承了一个抽象类C,那么这个普通类D不仅需要重写抽象类C中所有的抽象方法,还需要重写抽象类B中所有的抽象方法
//抽象类
abstract class Shape {
public abstract void draw();//抽象方法
}
//抽象类继承抽象类
abstract class Rect extends Shape {
// 不需要重写抽象方法
public abstract void func();
}
class D extends Rect {
@Override
public void draw() {
}
@Override
public void func() {
}
}
public class Text {
}
(6)抽象类(抽象方法)是不能被static或private修饰的
(7)抽象类最大的意义就是为了被继承,final和abstract是不能同时存在的(被final修饰的类是不能被继承的,而被final修饰的方法不能被重写)
(8)抽象类中不一定有抽象方法
(9)抽象方法没有加访问限定符时,默认是public
抽象类本身不能被实例化,要想使用,只能创建该抽象类的子类,然后让子类重写抽象类中的抽象方法
abstract class Shape {
public abstract void draw();
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("画○");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("画♦");
}
}
public class TextDame {
public static void shape(Shape shape){
shape.draw();
}
public static void main(String[] args) {
shape(new Cycle());
shape(new Rect());
}
}
接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用,在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型
被interface修饰的就是接口,java中的接口名称一般都会在前面加一个I,一个接口一般也是一个java文件
//接口
public interface IText {
}
(1)接口中的成员变量默认是public static final的
(2)接口中的方法默认是public abstract的
(3)接口中可以包含default修饰的方法,也可以被static修饰的方法
interface IShape {
public static void func(){
System.out.println("接口中的func方法");
}
default void function(){
System.out.println("接口中的function方法");
}
}
public class Text {
}
(4)接口不可以被实例化
(5)接口和类之间可以使用implements,表示这个类实现了这个接口,此时这个类就必须重写这个接口中所有的抽象方法
//接口IShape
interface IShape {
public abstract void draw();
}
//Cycle这个类就实现了IShape这个接口
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("画○");
}
}
public class Text {
}
(6)一个类实现接口的时候可以重写接口中的default修饰的方法
interface IShape {
public abstract void draw();
default void function(){
System.out.println("接口中的function方法");
}
}
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("画○");
}
//可以重写接口中的default修饰的方法
@Override
public void function() {
}
}
public class Text {
}
(7)一个类可以实现多个接口,接口之间用逗号隔开,此时这个类必须重写他所实现的多个接口中所有的抽象方法
package dame1;
interface IA {
void A ();
}
interface IB {
void B ();
}
interface IC {
void C ();
}
class E implements IA,IB,IC {
@Override
public void A() {
}
@Override
public void B() {
}
@Override
public void C() {
}
}
public class Text {
}
(8)一个类可以在继承某个抽象类或普通类的同时,实现接口,注意是先继承再实现
interface IA {
void A ();
}
class B {
}
class C extends B implements IA {
@Override
public void A() {
}
}
public class Text {
}
(9)当一个接口使用了extends拓展了其他接口,此时一个类实现这个接口,需要重写所有接口中的抽象方法。类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承,java中可以用接口可以达到多继承的目的
interface IA {
void A ();
}
interface IB {
void B ();
}
interface IC {
void C ();
}
interface ID extends IA,IB,IC {
void D ();
}
class E implements ID {
@Override
public void A() {
}
@Override
public void B() {
}
@Override
public void C() {
}
@Override
public void D() {
}
}
public class Text {
}
(10)接口中的方法是不能在接口中实现的,只能由实现接口的类来实现,接口中的抽象方法是不能带主体的
interface IA {
void A ();
// 报错
// public void A (){
//
// }
}
public class Text {
}
(11)接口中不能有静态代码块和构造方法
(12)接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
(13)如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
package dame2;
import java.util.Arrays;
class Student implements Comparable<Student>{
public int age;
public String name;
public double score;
public Student(int age, String name, double score) {
this.age = age;
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
public class Text {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student(18,"张三",38.8);
students[1] = new Student(58,"李四",8.8);
students[2] = new Student(8,"王五",28.8);
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
//结果:
// [Student{age=8, name='王五', score=28.8}, Student{age=18, name='张三', score=38.8}, Student{age=58, name='李四', score=8.8}]
}
import java.util.Arrays;
import java.util.Comparator;
class Student {
public int age;
public String name;
public double score;
public Student(int age, String name, double score) {
this.age = age;
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
//年龄比较器
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
//成绩比较器
class ScoreComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return (int)(o1.score - o2.score);
}
}
public class Text {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student(18,"张三",38.8);
students[1] = new Student(58,"李四",8.8);
students[2] = new Student(8,"王五",28.8);
AgeComparator ageComparator = new AgeComparator();
ScoreComparator scoreComparator = new ScoreComparator();
Arrays.sort(students,ageComparator);
System.out.println(Arrays.toString(students));
Arrays.sort(students,scoreComparator);
System.out.println(Arrays.toString(students));
}
//结果:
// [Student{age=8, name='王五', score=28.8}, Student{age=18, name='张三', score=38.8}, Student{age=58, name='李四', score=8.8}]
// [Student{age=58, name='李四', score=8.8}, Student{age=8, name='王五', score=28.8}, Student{age=18, name='张三', score=38.8}]
}
(1)浅拷贝:通过clone,我们只是拷贝了Person对象,但是Person对象中的Money对象,并没有拷贝。通过person2这个引用修改了money的值后,person这个引用访问money的时候,值也发生了改变。这里就是发生了浅拷贝
class Money implements Cloneable{
public double money = 10.1;
// 重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
public int id;
public Money money = new Money();
public Person(int id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Text2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person(1);
System.out.println(person);//dame2.Person@1b6d3586
Person person2 = (Person)person.clone();
System.out.println(person2);//dame2.Person@4554617c
System.out.println("修改money:");
person2.money.money = 99.9;
System.out.println(person.money.money);//99.9
System.out.println(person2.money.money);//99.9
}
}
Cloneable底层是一个空接口,也就是标记接口,证明实现该接口的类是可以被克隆的
(2)深拷贝:
class Money implements Cloneable{
public double money = 10.1;
// 重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
public int id;
public Money money = new Money();
public Person(int id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person personCopy = (Person) super.clone();
personCopy.money = (Money) this.money.clone();
return personCopy;
}
}
public class Text2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person(1);
System.out.println(person);//dame2.Person@1b6d3586
Person person2 = (Person)person.clone();
System.out.println(person2);//dame2.Person@4554617c
System.out.println("修改money:");
person2.money.money = 99.9;
System.out.println(person.money.money);//10.1
System.out.println(person2.money.money);//99.9
}
}
相同点:
不同点:
(1)Object是Java默认提供的一个类
(2)Java里面除了Object类,所有的类都是存在继承关系的,默认会继承Object父类。即Object类是所有类的父类
(3)父类引用引用子类对象,意为值object类可以引用任意数据类型
public class Text2 {
public static void main(String[] args) {
// Object接受数组对象,发生向上转型
Object array = new int[]{1,2,3};
// 向下转型(不安全),需要强转
int[] a = (int[]) array;
Object[] array1 = {1, 'c', false};
}
}
(1)如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
(2)如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
(3)equals方法底层也是按照地址比较的
class Student{
public int id;
public Student(int id) {
this.id = id;
}
}
public class Text2 {
public static void main(String[] args) {
Student student1 = new Student(1);
Student student2 = new Student(1);
System.out.println(student1 == student2);//false
System.out.println(student1.equals(student2));//false
}
}
(4)如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的
class Student{
public int id;
public Student(int id) {
this.id = id;
}
// 重写equals方法
@Override
public boolean equals(Object obj) {
if(obj == null){
return false;
}
if (this == obj){
return true;
}
// 如果obj不是Student,返回false
if (!(obj instanceof Student)){
return false;
}
Student tmp = (Student) obj;//向下转型,比较属性值是否相等
return this.id == tmp.id;
}
}
public class Text2 {
public static void main(String[] args) {
Student student1 = new Student(1);
Student student2 = new Student(1);
System.out.println(student1 == student2);//false
System.out.println(student1.equals(student2));//true
}
}
要打印对象中的内容,可以直接重写Object类中的toString()方法
import java.util.Arrays;
class Student {
public int age;
public String name;
public double score;
public Student(int age, String name, double score) {
this.age = age;
this.name = name;
this.score = score;
}
// 重写toString方法
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
public class Text {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student(18,"张三",38.8);
students[1] = new Student(58,"李四",8.8);
students[2] = new Student(8,"王五",28.8);
System.out.println(Arrays.toString(students));
//[Student{age=18, name='张三', score=38.8}, Student{age=58, name='李四', score=8.8}, Student{age=8, name='王五', score=28.8}]
}
}
(1)不重写HashCode方法,两个对象的hash值不一样
import java.util.Objects;
class Student{
public int id;
public Student(int id) {
this.id = id;
}
}
public class Text2 {
public static void main(String[] args) {
Student student1 = new Student(1);
Student student2 = new Student(1);
System.out.println(student1.hashCode());//460141958
System.out.println(student2.hashCode());//1163157884
}
}
(2)重写HashCode方法
import java.util.Objects;
class Student{
public int id;
public Student(int id) {
this.id = id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
public class Text2 {
public static void main(String[] args) {
Student student1 = new Student(1);
Student student2 = new Student(1);
System.out.println(student1.hashCode());//32
System.out.println(student2.hashCode());//32
}
}