第十二天笔记

重写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);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值