之前我在一篇博客中有提到接口这个问题,接口在Java实际操作中是每个程序员每天都会用到的。本次主要讲一下博主对类与类之间的关系(主要还是接口)以及Object中部分方法。
类与类之间的关系
这里说一下个人见解。
其实类型和类型直接的关系无非就是三个关键字is、has、like
三种比喻
1.is a:
比如:Cat is a/an Animal(猫是一个动物)
凡是满足is a的表示继承关系
Cat extends Animal{}
(这个例子在先前文章中有具体实例,这里就暂且理解一下)
2.has a:
Customer has a FoodMenu(顾客有一个菜单)
凡是能够满足has a关系的表示关联关系
关联关系通常以属性的形式存在
class Customer{
FoodMenu foodmenu;
}
3.like a:
Cooker like a FoodMenu(厨师就像一个菜单一样能做菜单上的菜)
凡是能够满足like a关系的表示实现关系
实现关系通常是:类实现接口
Cooker implements FoodMenu{}
代码实例
这里的厨师、菜单、顾客例子我们写一个实例来体现一下其中的关系
创建菜单接口
//接口:菜单
public interface FoodMenu {
void chaoJiDan();
void yuXiangRouSi();
}
创建厨师
//中餐厨师是接口的实现者1
public class ChinaCooker implements FoodMenu{
@Override
public void chaoJiDan() {
System.out.println("中餐师傅做的炒鸡蛋");
}
@Override
public void yuXiangRouSi() {
System.out.println("中餐师傅做的鱼香肉丝");
}
}
//西餐厨师是接口的实现者2
public class AmerricanCooker implements FoodMenu{
@Override
public void chaoJiDan() {
System.out.println("西餐师傅做的炒鸡蛋");
}
@Override
public void yuXiangRouSi() {
System.out.println("西餐师傅做的鱼香肉丝");
}
}
顾客类关联到菜单接口
//顾客类
public class Customer {
//Customer has a Foodmenu!
//凡是可以使用 has a来描述的,统一以属性的形式存在
private FoodMenu foodMenu;
//无参构造
public Customer() {
}
//有参构造
public Customer(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
//setter and getter
public FoodMenu getFoodMenu() {
return foodMenu;
}
public void setFoodMenu(FoodMenu foodMenu) {
this.foodMenu = foodMenu;
}
//点菜的方法
public void order(){
getFoodMenu().chaoJiDan();
getFoodMenu().yuXiangRouSi();
}
}
测试类
public class Test {
public static void main(String[] args) {
//创建厨师
FoodMenu cooker1=new ChinaCooker();
//创建顾客
Customer customer1=new Customer(cooker1);
//顾客点菜
customer1.order();
}
}
实现结果:
中餐师傅做的炒鸡蛋
中餐师傅做的鱼香肉丝
这个例子其实就很好的体现了接口与类之间的关系,能够发现菜单(接口)、厨师(类)、顾客(类)这三者并没有直接接触,而是通过接口将二者联系起来,非常巧妙。
Object类中部分方法
1.toString()方法
实际操作中基本上所有类的toString方法都是需要重写的
重写规则:越简单越好
System.out.println(引用);这里会自动调用引用的toString方法
String类是SUN写的,String类的toString方法已经重写了
设计目的:通过调用这个方法可以将一个“java对象”转换成“字符串”的表现形式
toString()实例:
class Test{
public static void main(String[] args) {
Test01 test01=new Test01(2020,05,31);
System.out.println(test01.toString());
}
}
public class Test01 {
private int year;
private int month;
private int day;
public Test01() {
}
public Test01(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
//重写toString()方法
public String toString(){
return getYear()+"年"+getMonth()+"月"+getDay()+"日";
}
}
//输出结果:
//2020年5月31日
如果我们不重写toString()方法的话这里直接输出引用是不会有这样的结果。
2.equals()方法
所有的类equals方法也需要重写,因为Object中的equals方法比较的是两个对象的内存地址,我们应该比较对象的内容,所以需要重写。
重写规则:自己定,主要看是什么和什么相等时,表示俩对象相等
基本数据类型比较:==
对象和对象比较:调用equals方法
String类是SUN写的,String类的equals方法已经重写了。
Object类中的equals源代码:
public boolean equals(Object obj){
return(this==obj);}
判断两个对象的内存地址是否相同用“==”
而判断两个对象是否相等,需要在子类中重写equals()方法。
实例:
public class Test02 {
public static void main(String[] args) {
MyTime myTime1=new MyTime(2008,8,8);
MyTime myTime2=new MyTime(2008,8,8);
//重写之前这里的“==”判断的是两个对象的内存地址是否相等
//重写之前System.out.println(myTime1 == myTime2);
//重写之后
System.out.println(myTime1.equals(myTime2));
}
}
class MyTime {
private int year;
private int month;
private int day;
public MyTime() {
}
public MyTime(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
//重写equals方法(用IDEA会自动生成)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyTime myTime = (MyTime) o;
return year == myTime.year &&
month == myTime.month &&
day == myTime.day;
}
}
myTime1.equals(myTime2)这两者做比较输出的结果是个布尔类型
此案例中它们两者确实相同,所以输出结果为true
其他俩个方法因为作者学习到目前并没有很常用,所以只是简单介绍一下:
3.finalize()方法
protect void finalize() throws Throwable{};
1.在Object中的源代码:
2.只有方法体,里面没代码
3.这个方法不需要程序员手动调用
4.执行时机:
当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用这个方法
5.finalize()方法实际上是SUN公司为java程序员准备的一个时机:垃圾回收时机
如果需要在垃圾回收的时候执行一段代码的话,可以将代码写入此方法:
protected void finalize() throws Throws{
//方法体;
}
4.hashCode()方法
public native int hashCode();
hashCode()返回的时候哈希码:
实际上是一个java对象的内存地址经过哈希算法,得出的一个值
所以hashCode()方法的执行结果可以等同看做一个java对象的内存地址