动态绑定机制(🚩🚩🚩非常重要)
!!!
- 调用方法时会和该对象的运行类型(内存地址)绑定
- 调用属性是不发生绑定,即为,在哪声明,在哪调用
public class Dynamicbinding{
public static void main(String[] args){
A a=new B();
//正常情况,方法调用看运行类型即B;
a.sum();//40
a.sum1();//30
//若B类sum()被注销
a.sum();
/*30;此时A类的sum中的getI()发生动态绑定。即为getI()会绑定为运 行类型;即为B下的getI();若没有,遵循向上查找*/
}
}
class A{
public int i=10;
public int sum(){
return getI()+10;
}
public int getI(){
return i;
}
public int sum1(){
return getI()+20;
}
}
class B extends A{
public int i=20;
/* public int sum(){
return getI()+20;
}*/
public int getI(){
return i;
}
public int sum1(){
return getI()+10;
}
}
多态的应用
1.多态数组
数组定义类型为父类类型,数组元素为子类类型
语法:
Person[] arr=new Person[3]; arr[0]=new Student("jack",21,151); arr[1]=new Student("luss",20,125); arr[2]=new Teacher("tom",32,23111);
问题:
-
访问子类共有方法
for (int i = 0; i <arr.length ; i++) { arr[i].say(); }
-
访问子类特有方法(使用instanceOf判断元素运行类型,然后向下转型)
for (int i = 0; i <arr.length ; i++) { arr[i].say(); if(arr[i] instanceOf Student){ ((Student)arr[i]).learn();//判断运行类型为学生,则调用学习方法 }else if(arr[i] insatnceOf Teacher){ ((Teacher)arr[i]).teach();//判断运行类型为老师,则调用教学方法 } }
2.多态参数
即把上述访问子类特有方法封装成方法,在main栈调用
public class Poly_par{
public static void main(String[] args){
Person[] arr=new Person[1];
arr[0]=new Student("zhansan",21,151);
(new Poly_par()).show();
}
public void show(Person[] arr){//即为多态参数
for (int i = 0; i <arr.length ; i++) {
arr[i].say();
if(arr[i] instanceOf Student){
((Student)arr[i]).learn();//判断运行类型为学生,则调用学习方法
}else if(arr[i] insatnceOf Teacher){
((Teacher)arr[i]).teach();//判断运行类型为老师,则调用教学方法
}
}
}
}
系统方法
1.比较运算符 ==
- 🚩基本类型比较:值
- 🚩引用类型比较:地址
2.equals()方法
由于是Object类中的方法,只能比较引用类型
一般默认比较地址是否相等,通常子类会重写equals方法(如:字符串比较;会变成两个串的值比较)
//jdk源码 String 重写equals方法 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i])//⚡ 这里即为值比较 return false; i++; } return true; } } return false; }
思考
String s1=new String("og80");
String s2=new String("og80");
s1==s2//false,此时比较的是两个地址是否相同
s1.equals(s2)//true,⚡此时比较字符串的值是否相等
自定义重写equals
-
要求两个对象属性一致,返回true;
如:
Per p=new Per("name",21); Per p1=new Per("name",21);
若不重写,上述为false
//重写equals public class Override_equals{ public static void main(String[] args){ Per p=new Per("name",21); Per p2=new Per("name",21); p.equals(p2);//此时为true } } class Per{ public int age; public String name; poublic Per(String name,int age){ this.name=name; this.age=age; } public boolean equals(Object obj){ if(this==obj){ return true; } if(obj instanceof Per){ Per p=(Per)obj; return this.name.equals(p.name) && this.age.equals(p.age); } return false; } }
3.haspCode()方法
作用:
- 提高具有哈希结构的容器效率
- 两个引用如果指向同一个对象,haspCode值一定相同
- haspCode是由jvm虚拟机地址换算而来,不等于地址值;
- 后续学习集合时,会重写haspCode()
4.toString()方法
介绍:
- 默认返回:全类名+@+哈希值的十六进制(全类名即为包名加类名)
- 重写toString()方法
- 直接输出对象时会默认调用toString()方法
toString()的jdk源码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
toString()方法重写
class Tos{
public String name;
public int age;
@Override
public String toString() {//输出对象属性;也可自定义
return "Tos{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
5.finalize()方法
- 当对象被回收时,系统自动调用该方法,子类可重写
- 何时对象被回收:当某个对象没有任何引用时,jvm把该对象作为垃圾进行销毁;销毁之前调用finalize()方法
- 垃圾回收机制有系统决定,也可通过System.gc()主动触发