文章目录
前言
一、抽象类
1.1 抽象类的概念
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象方法:被abstract修饰的方法,没有方法体。
包含抽象方法的类我们称为抽象类。
1.2 抽象类语法结构
在Java中,一个类如果被 abstract 修饰就称之为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。
1.3 抽象类的特性
- 抽象类是被abstract修饰的,被abstract修饰的方法称为抽象方法,该方法可以没有具体的实现,但是当一个类中含有抽象方法的时候,该类必须使用abstract修饰。
- 抽象类当中可以有和普通类一样的成员变量和成员方法。这也就意味着: 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类。所以,当普通类继承了抽象类之后,这个普通类一定要重写这个抽象类当中所有的抽象方法。
- 抽象方法不能是 private 的。
- 抽象方法不能被final和static修饰,因为抽象方法要被子类重写,但final修饰的不可以被重写。
- 抽象类不能直接实例化对象,这也就意味着抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰。
- 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量。
1.4 抽象类代码示例
abstract class Shape{
public Shape(){
//用来让继承的子类替它进行实例化
}
public abstract void draw();
public void test(){
}
}
class Rest extends Shape{
@Override
public void draw() {
System.out.println("矩形");
}
}
class Circle extends Shape{
@Override
public void draw() {
System.out.println("圆形");
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("花朵");
}
}
public class TestDemo {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
drawMap(new Rest());
drawMap(new Circle());
drawMap(new Flower());
}
}
结果如下
二、接口
2.1 接口的定义
1.使用Interface来定义一个接口。
2.接口当中的成员变量默认是public static final的,成员方法默认是public abstract的,一般情况下可以直接省略。
3.接口中不可以直接出现普通方法,除非在普通方法前面用default修饰,这样的方法可以被具体实现。
4.如果接口当中的当普通方法被static修饰,那么这样的方法也可以被具体实现。
5.接口不能通过new关键字来进行实例化,在类和接口之间,需要通过关键字implement来实现接口,该类中需要实现接口中的所有方法。
6.接口也可以产生向上转型和动态绑定。
2.2 接口使用
2.2.1 代码示例(一)
public interface IShape{
int a = 10;
void draw();
default public void test(){
System.out.println("test()");
}
public static void test2(){
System.out.println("stctic");
}
}
class Rect implements IShape{
@Override
public void draw() {
System.out.println("矩形");
}
}
class Circle implements IShape{
@Override
public void draw() {
System.out.println("圆形");
}
}
class Flower implements IShape{
@Override
public void draw() {
System.out.println("花朵");
}
}
public class Test {
public static void drawMap(IShape iShape){
iShape.draw();
}
public static void main(String[] args) {
drawMap(new Rect());
drawMap(new Circle());
drawMap(new Flower());
}
}
结果如下
2.2.2 接口使用代码示例(二)
public interface IUSB {
void openDevice();
void closeDevise();
}
class Mouse implements IUSB{
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevise() {
System.out.println("关闭鼠标");
}
public void click(){
System.out.println("鼠标点击");
}
}
class KeyBoard implements IUSB {
@Override
public void openDevice() {
System.out.println("打开键盘");
}
@Override
public void closeDevise() {
System.out.println("关闭键盘");
}
public void inPut(){
System.out.println("键盘输入");
}
}
class Computer{
public void powerOn() {
System.out.println("打开笔记本电脑");
}
public void powerOff() {
System.out.println("关闭笔记本电脑");
}
public void useDevise(IUSB usb){
usb.openDevice();
if(usb instanceof Mouse){
Mouse mouse = (Mouse) usb;
mouse.click();
}else if(usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.inPut();
}
usb.closeDevise();
}
}
public class Test {
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();
computer.useDevise(new Mouse());
computer.useDevise(new KeyBoard());
computer.powerOff();
}
}
结果如下
2.2.3 接口使用代码示例(三)
public interface IFiying {
void fly();
}
public interface IRunning{
void run();
}
public interface ISwimming {
void swim();
}
public abstract class Animal {
public String name;
public int age;
public Animal(String name,int age){
this.name = name;
this.age = age;
}
public abstract void eat();
}
public class Bird extends Animal implements IRunning,IFiying{
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name + "正在吃鸟食");
}
@Override
public void fly() {
System.out.println(name + "正在用翅膀飞翔");
}
@Override
public void run() {
System.out.println(name + "正在用鸟腿跑步");
}
}
public class Dog extends Animal implements IRunning,ISwimming{
public Dog(String name,int age){
super(name,age);
}
@Override
public void eat() {
System.out.println(name + "正在吃狗粮");
}
@Override
public void run() {
System.out.println(name + "正在奔跑");
}
@Override
public void swim() {
System.out.println(name + "正在狗刨");
}
}
public class Test {
public static void test(Animal animal){
animal.eat();
}
public static void test1(IFiying iFiying){
iFiying.fly();
}
public static void test2(IRunning iRunning){
iRunning.run();
}
public static void test3(ISwimming iSwimming){
iSwimming.swim();
}
public static void main(String[] args) {
Dog dog = new Dog("小狗",1);
Bird bird = new Bird("小鸟",2);
test(dog);
test(bird);
System.out.println("================");
test1(bird);
System.out.println("================");
test2(dog);
test2(bird);
System.out.println("================");
test3(dog);
}
}
结果如下
2.2.4 接口使用代码示例(四)
class Student implements Comparable<Student>{
public String name;
public 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) {
return this.age - o.age;
}
}
public class Test {
public static void main(String[] args) {
Student student1 = new Student("张三",12);
Student student2 = new Student("王五",5);
System.out.println(student1.compareTo(student2));
}
}
结果如下
2.2.5 接口使用代码示例(五)
class Student implements Comparable<Student>{
public String name;
public 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.age > o.age){
return 1;
} else if (this.age > o.age) {
return -1;
}else {
return 0;
}
}
}
public class Test {
public static void main(String[] args) {
Student student1 = new Student("张三",12);
Student student2 = new Student("王五",5);
System.out.println(student1.compareTo(student2));
}
}
结果如下
2.2.6 接口使用错误代码示例
class Student{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三",10);
students[1] = new Student("王五",12);
students[2] = new Student("李四",5);
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}
结果如下
2.2.6 接口使用正确代码示例
class Student implements Comparable<Student>{
public String name;
public 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) {
return this.age - o.age;
}
}
public class Test {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("张三",10);
students[1] = new Student("王五",12);
students[2] = new Student("李四",5);
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}
结果如下
2.2.7 接口使用代码示例(六)
class Student implements Comparable<Student>{
public String name;
public 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) {
return this.age - o.age;
}
}
public class Test {
public static void bubbleSort(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("张三",10);
students[1] = new Student("李武",14);
students[2] = new Student("王五",1);
bubbleSort(students);
System.out.println(Arrays.toString(students));
}
}
结果如下
2.2.8 接口使用代码示例(七)
class Student implements Cloneable {
public 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();
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException{
Student student1 = new Student(10);
Student student2 = (Student) student1.clone();
System.out.println(student1);
System.out.println(student2);
}
}
结果如下
2.3 接口特性
- 接口类型是一种引用类型,但是不能直接new接口的对象。
- 接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public abstract,其他修饰符都会报错。
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现。
- 重写接口中方法时,不能使用默认的访问权限。
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量。
- 接口中不能有静态代码块和构造方法。
- 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class。
- 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类。
- jdk8中:接口中还可以包含default方法。。
2.4 抽象类和接口的区别(※)
核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用, 而接口中不能包含普通方法, 子类必须重写所有的抽象方法。
三、Object 类
3.1 什么是Object 类?
Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object的引用进行接收。
3.2 获取对象信息
3.2.1 父类获取对象信息
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("张三",12);
System.out.println(person);
}
}
结果如下
3.2.2 子类重写toString( )获取对象信息
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("张三",12);
System.out.println(person);
}
}
结果如下
3.3 对象比较equals方法
在Java中,== 进行比较时:
如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同;
如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同;
如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的;
3.3.1 对象比较equals方法代码示例(一)
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("张三",12);
System.out.println(person1);
Person person2 = new Person("张三",12);
System.out.println(person2);
System.out.println(person1 == person2);
System.out.println("=============");
System.out.println(person1.equals(person2));
}
}
结果如下
3.3.1 对象比较equals方法代码示例(一)
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@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);
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("张三",12);
System.out.println(person1);
Person person2 = new Person("张三",12);
System.out.println(person2);
System.out.println(person1 == person2);
System.out.println("=============");
System.out.println(person1.equals(person2));
System.out.println("=============");
Person person3 = person2;
System.out.println(person3.equals(person2));
}
}
结果如下
3.4 hashcode方法
3.4.1 原hashcode方法调用
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("张三",12);
Person person2 = new Person("张三",12);
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
}
}
3.4.1 重写hashcode方法调用
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("张三",12);
Person person2 = new Person("张三",12);
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
}
}
结果如下
3.4.2 学习小贴士
1、hashcode方法用来确定对象在内存中存储的位置是否相同。 2、事实上hashCode()
在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的 散列码,进而确定该对象在散列表中的位置。
四、深拷贝代码示例
class Money implements Cloneable{
public double money = 19.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable {
public int age;
public Money m;
public Student(int age){
this.age = age;
this.m = new Money();
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student str = (Student) super.clone();
str.m = (Money) this.m.clone();
return str;
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException{
Student student1 = new Student(10);
Student student2 = (Student) student1.clone();
System.out.println(student1);
System.out.println(student2);
System.out.println("================");
System.out.println(student1.m.money);
System.out.println(student2.m.money);
System.out.println("================");
student2.m.money = 99.8;
System.out.println(student1.m.money);
System.out.println(student2.m.money);//浅拷贝
System.out.println("================");
}
}
结果如下