第十二天笔记

    科技2022-08-16  109

    重写Object类方法&抽象类&接口

    1.重写Object类方法

    1.1 hashCode方法

    hashCode方法本身作用?

    hashCode本身属于Object提供的一个用于获取对象hash值十进制的方法

    hashCode,hash值是什么东西?

    hash值是JVM根据杂凑算法 将对象的地址或者其他系信息作为条件计算出来的一个值 这个值一般情况下保证可以唯一性

    hash算法举例:根据每人的姓氏的笔画除以某个数再加上某个数,决定你要在第几排第几列,正向是快速的但是不可以逆转的 例子:王 丰

    hash值和地址的关系?

    hash值仅仅只是地址的表现形式并不能代表地址 Java中生成hash的原码我们是看不到的 因为底层是使用C语言来写的

    两个对象的hash值相同不一定是同一个对象,两个一致的对象hash值一定相同

    为什么要重写hashCode方法?

    在一些散列的数据结构中,有这样的要求 如果两个对象使用equals比较为true 那么这两个对象hash值必须一致,所以我们实际开发中,如果重写了equals方法,必须重写hashCode方法

    package com.qfedu.test2; /** * 重写hashCode方法 * hashCode方法本身作用? * hashCode本身属于Object提供的一个用于获取对象hash值十进制的方法 * hashCode,hash值是什么东西? * hash值是JVM根据杂凑算法 将对象的地址或者其他信息等作为条件 * 计算出来的一个数值 这个数值一般情况保证下可以唯一性 * hash算法举例:根据每个人姓氏的笔画数决定你在第几排 根据你名字的笔画数除以某个数 再加上某个数 得到你应该在第几列 * 正向是快速的 但是不可逆的 王 丰 * hash值和地址的关系? * hash值仅仅只是地址的表现形式 并不能代表地址 Java中的生成hash的原码我们是看不到的 因为底层是使用C语言来写的 * 两个对象hash值相同 不一定是同一个对象 两个一致的对象 hash值一定相同 * 为什么要重写hashCode方法? * 在一些散列的数据结构中 有这样的要求 如果两个对象使用equals比较为true 那么这两个对象hash值必须一致 * 所以我们在实际开发中 如果重写了equals方法 必须重写hashCode方法 * @author WHD * */ public class Person extends Object{ private String name; // 名字 private String idCard; // 身份证 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } public Person(String name, String idCard) { this.name = name; this.idCard = idCard; } public Person() { } public boolean equals(Object obj) { if(this == obj) { return true; } Person p = (Person) obj; if(this.getName().equals(p.getName()) && this.getIdCard().equals(p.getIdCard())) { return true; } return false; } public int hashCode() { int prime = 31; // 权重 特殊的质数 int result = 1; // 结果先赋值为1 接下来计算 然后返回 result = prime * result + (this.getName() == null ? 0 : this.getName().hashCode()); result = prime * result + (this.getIdCard() == null ? 0 :this.getIdCard().hashCode()); return result; } public static void main(String[] args) { Person p1 = new Person("赵四","1578721247856121"); Person p2 = new Person("赵四","157872124785612dsadsadasd1"); System.out.println(p1.hashCode()); System.out.println(p2.hashCode()); System.out.println("返回当前所在类的Class对象" + p1.getClass().toString()); System.out.println("包名+类名" + p1.getClass().getName()); } }
    1.2getClass()方法

    此方法返回的是一个Class类型的对象,继续调用getName()方法,返回当前对象的包名+类名(全限定名)

    2. 抽象类

    抽象 类 不是特别具体的一个类别

    抽象:模糊不具体

    1.抽象方法和抽象类都使用abstract关键字修饰

    2.抽象方法没有方法体 必须存在于抽象类中

    3.抽象类不能直接new对象 必须通过多态的方式来创建对象 new子类的方式

    4.子类必须重写父类的抽象方法,除非子类也是抽象类

    5.没有抽象的静态方法 没有抽象的构造方法

    抽象类和普通类的区别?

    1.抽象类可以写抽象方法,普通类不行

    抽象类作为父类,实现多态的方式 依然是父类作为形参父类作为返回值

    总结:抽象类使用感受

    抽象类可以定义抽象方法 用于强制子类实现 这样可以统一我们程序的整体结构 更加规范

    package com.qfedu.test3; /** * 门 * 属性: * 品牌 * 价格 * 行为: * 开 * 关 * 门: * 普通门 * 防盗门 * @author WHD * */ public abstract class Door { private String brand; private double price; public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public abstract void open(); public abstract void close(); } package com.qfedu.test3; /** * 普通门 * @author WHD * */ public class CommonDoor extends Door{ @Override public void open() { System.out.println("普通门开门,钥匙一插,轻轻一转,门开了"); } @Override public void close() { System.out.println("甩手一关门"); } } package com.qfedu.test3; public class SecurityDoor extends Door{ @Override public void open() { System.out.println("指纹+人脸识别,门开了"); } @Override public void close() { System.out.println("红外线感应,自动关门"); } } package com.qfedu.test3; /** * 人类 * 用于操作门 * 关门 * 开门 * @author WHD * */ public class Person { public void openCommonDoor(CommonDoor cd) { cd.open(); } public void openSecurityDoor(SecurityDoor sd) { sd.open(); } public void closeCommonDoor(CommonDoor cd) { cd.close(); } public void closeSecurityDoor(SecurityDoor sd) { sd.close(); } // 以上四个方法不合理 如果有的子类 必须重复编写新的方法 // 使用以下两个方法能够解决这个问题 public void openDoor(Door door) { door.open(); } public void closeDoor(Door door) { door.close(); } public CommonDoor buyCommomDoor() { return new CommonDoor(); } public SecurityDoor buySecurityDoor() { return new SecurityDoor(); } public Door buyDoor(String type) { if(type.equals("普通")) { return new CommonDoor(); }else if(type.equals("安全")) { return new SecurityDoor(); } return null; } } package com.qfedu.test3; public class Test { public static void main(String[] args) { Door door1 = new CommonDoor(); Person zhaosi = new Person(); zhaosi.openDoor(door1); zhaosi.closeDoor(door1); Door door2 = new SecurityDoor(); zhaosi.openDoor(door2); zhaosi.closeDoor(door2); Door door3 = zhaosi.buyDoor("普通"); zhaosi.openDoor(door3); } }

    3.final关键字

    final 单词:最终

    可以

    1.修饰属性

    ​ 使用final修饰的属性称之为常量,如果在程序需要使用一个不能改变的值,那么可以使用final修饰

    ​ final修饰的常量名全部要大写,多个单词之间使用下划线分割

    普通常量:

    ​ 通常在定义的时候赋值也可以在构造方法中赋值,只能被赋值一次,使用类名直接访问

    2.修饰方法:此方法不能被重写,可以被继承

    3.修饰类:此类不能被继承

    package com.qfedu.test4; /** * final 最终 * 修饰属性 常量 * 1.通常在声明的时候直接赋值 * 2.在构造方法中赋值也可以 * 修饰方法 * 1.被final修饰的方法可以被继承 ,不能被重写 * 修饰类 * 1.修饰类不能被继承 * @author WHD * */ public class TestFinal { final double PI = 3.14; //方式1 定义的时候赋值 private final int A ; public TestFinal() { A = 20; // 方式2 在构造方法中赋值 } public static void main(String[] args) { TestFinal tf = new TestFinal(); System.out.println(tf.A); // tf.a = 20; A a = new A(); a.m1(); } } class MySuper{ public final void m1() { System.out.println("MySuper类中的m1方法"); } } class A extends MySuper{ // final修饰的方法 不能被重写 // @Override // public void m1() { // // } } final class B{ } //class C extends B{ 不能继承B类 因为 B类使用final修饰 // //} //class D extends String{ // //} package com.qfedu.test4; /** * 使用final修饰的属性我们称之为常量 * 常量的作用: * 1.如果在程序执行过程中不想要一个值被改变 就可以使用final修饰 比如 PI 圆周率 * 2.使用final修饰的常量只能被赋值一次 * 3.通常在定义的时候赋值 也可以在 构造方法(没有加static修饰的)或者 静态代码块(加上static修饰的)中赋值 * 常量的写法要求 :全部大写 多个单词之间使用下划线分割 * 在日常开发中 通常将static和final结合一起来使用 因为如果一个内容不允许被改变 那么这个内容通常也没有必要存在多个 * @author WHD * */ public class TestFinalField { public static final double PI = 3.14; // 方式1 定义的时候赋值 使用的最多的方式 public static final String COUNTRY_NAME; static { COUNTRY_NAME = "中国"; // 方式2 在静态代码块中赋值 } // 以上两种方式都是为了保证在使用在这个信息之前 这个静态常量就有值了 public static void main(String[] args) { System.out.println(TestFinalField.PI); System.out.println(TestFinalField.COUNTRY_NAME); } }
    Processed: 0.010, SQL: 9