314. 动态绑定机制
【注】属性没有动态绑定机制
虽然B类sum被注释掉了,但是其父类A类的sum方法没被注释掉,所以调用的是A类的sum方法,A类的sum方法中有个getI()方法,根据动态绑定机制,现在这个a引用的运行类型是B类,子类B里恰好也有getI()方法,所以调用getI()的时候先从子类B找,发现子类B有getI()方法,就调用子类B的getI()方法,子类B的getI()对应的返回的是B类的属性i,属性没有动态绑定机制,所以getI()返回20.
315. 多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组
中,并调用每个对象
say 方法. 应用实例升级:如何调用子类特有的方法,比如
Teacher 有一个 teach , Student 有一个 study
怎么调用?
Person.java
package com.Marisa.ployarr_;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String say(){
return "name:" + name + "\t" + "age:" + age + "\t";
}
}
Student.java
package com.Marisa.ployarr_;
public class Student extends Person{
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
//重写父类say方法
@Override
public String say() {
return "学生:\t" + super.say() + "socre:" + score + "\t";
}
}
Teacher.java
package com.Marisa.ployarr_;
public class Teacher extends Person{
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//重写父类say方法
@Override
public String say() {
return "老师:\t" + super.say() + "salary" + salary + "\t";
}
}
PoloArray.java
package com.Marisa.ployarr_;
public class PoloArray {
public static void main(String[] args) {
Person[] persons = new Person[5];
persons[0] = new Person("田所浩二", 24);
persons[1] = new Student("德川", 26, 114514);
persons[2] = new Student("我修院", 26, 114514);
persons[3] = new Teacher("王爷", 114514, 114514);
persons[4] = new Teacher("淳平", 114514, 114514);
//循环遍历多态数组,调用say
for (int i = 0; i < persons.length; i++) {
//persons[i] 编译类型是Person,运行类型是根据实际情况有JVM判断
System.out.println(persons[i].say());//动态绑定机制
}
}
}
运行结果:
name:田所浩二 age:24
学生: name:德川 age:26 socre:114514.0
学生: name:我修院 age:26 socre:114514.0
老师: name:王爷 age:114514 salary114514.0
老师: name:淳平 age:114514 salary114514.0
316. 多态数组2
为Student类和Teacher类加入特有方法
Student.java
package com.Marisa.ployarr_;
public class Student extends Person{
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
//重写父类say方法
@Override
public String say() {
return "学生:\t" + super.say() + "socre:" + score + "\t";
}
public void study(){
System.out.println("学生" + getName() + "正在嗯嘛啊");
}
}
Teacher.java
package com.Marisa.ployarr_;
public class Teacher extends Person{
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//重写父类say方法
@Override
public String say() {
return "老师:\t" + super.say() + "salary" + salary + "\t";
}
//特有的方法
public void teach(){
System.out.println("老师" + getName() + "正在授课");
}
}
PoloArray.java
package com.Marisa.ployarr_;
public class PoloArray {
public static void main(String[] args) {
Person[] persons = new Person[5];
persons[0] = new Person("田所浩二", 24);
persons[1] = new Student("德川", 26, 114514);
persons[2] = new Student("我修院", 26, 114514);
persons[3] = new Teacher("王爷", 114514, 114514);
persons[4] = new Teacher("淳平", 114514, 114514);
//循环遍历多态数组,调用say
for (int i = 0; i < persons.length; i++) {
//persons[i] 编译类型是Person,运行类型是根据实际情况有JVM判断
System.out.println(persons[i].say());//动态绑定机制
//调用特有方法
//判断运行类型是不是Student
if(persons[i] instanceof Student){
((Student)persons[i]).study();//向下转型
}
//判断是Teacher
else if(persons[i] instanceof Teacher){
((Teacher)persons[i]).teach();
}
}
}
}
运行结果:
name:田所浩二 age:24
学生: name:德川 age:26 socre:114514.0
学生德川正在嗯嘛啊
学生: name:我修院 age:26 socre:114514.0
学生我修院正在嗯嘛啊
老师: name:王爷 age:114514 salary114514.0
老师王爷正在授课
老师: name:淳平 age:114514 salary114514.0
老师淳平正在授课
317. 多态参数
Employee.java
package com.Marisa.polyparameter_;
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//得到年工资
public double getAnnual(){
return 12 * salary;
}
}
Manager.java
package com.Marisa.polyparameter_;
public class Manager extends Employee{
private double bonus;
public Manager(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
//管理
public void manage(){
System.out.println("经理" + getName() + "正在管理");
}
//重写获取年薪方法
//加奖金金金金金金
@Override
public double getAnnual() {
return super.getAnnual() + bonus;
}
}
Worker.java
package com.Marisa.polyparameter_;
public class Worker extends Employee{
public Worker(String name, double salary) {
super(name, salary);
}
public void work(){
System.out.println("普通员工" + getName() + "正在工作");
}
//普通员工没用其他收入,则直接调用父类
@Override
public double getAnnual() {
return super.getAnnual();
}
}
Test.java
package com.Marisa.polyparameter_;
public class Test {
public static void main(String[] args){
Worker w1 = new Worker("我修院", 114514);
Manager m1 = new Manager("淳平", 114514, 1919);
Test test = new Test();
test.showmpAnnual(w1);
test.showmpAnnual(m1);
test.testWork(w1);
test.testWork(m1);
}
public void showmpAnnual(Employee e){
System.out.println(e.getAnnual());//动态绑定机制
}
//添加testWork方法,如果普通员工,调用work方法
//如果是经理,调用manage方法
public void testWork(Employee e){
if(e instanceof Worker){
((Worker)e).work();//向下转型操作
}else if(e instanceof Manager){
((Manager)e).manage();
}else{
System.out.println("不做处理……");
}
}
}
运行结果:
1374168.0
1376087.0
普通员工我修院正在工作
经理淳平正在管理
318. ==运算符
package com.Marisa.object_;
public class Equals01 {
public static void main(String[] args) {
A a = new A();
A b = a;
A c = b;
//==判断两个引用是否指向同一个对象
System.out.println(a == c);
System.out.println(a == b);
B bobj = a;
System.out.println(bobj == c);
}
}
class B{
}
class A extends B{
}
运行结果
true
true
true
319. 查看JDK源码
查看方法看视频
320. 子类重写equals
String重写的equals
Object类的equals方法
Integer类的euqals方法
==只判断对象的地址是否相等
equals经过重写后判断的是值是否相等
321. equals课堂练习1
应用实例: 判断两个 Person 对象的内容是否相等,如果两个 Person 对象的各个属性值都一样,则返回 true,反之 false。
Person.java
package com.Marisa.equals_;
public class Person {
private String name;
private int age;
private char gender;
public Person(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
//如果两个是同一个引用(指向同一个地址,直接返回true)
if(this == obj){
return true;
}
//如果不是Person对象,返回false
if(!(obj instanceof Person)){
return false;
}else{
//是Person对象,判断值是否都相等
Person temp = (Person)obj;//先将运行类型转换为Person
return this.name.equals(temp.name) &&
this.age == temp.age &&
this.gender == temp.gender;
}
}
}
EqualsTest.java
package com.Marisa.equals_;
public class EqualsTest {
public static void main(String[] args) {
Person person1 = new Person("田所浩二", 24, '男');
Person person2 = new Person("田所浩二", 24, '男');
Person person3 = new Person("德川", 26, '男');
System.out.println(person1.equals(person2));
System.out.println(person1.equals(person3));
System.out.println(person1.equals(person1));
System.out.println(person1.equals(new String("123")));
}
}
运行结果:
true
false
true
false
322. equals课堂练习2
输出:
false
true
false//没重写equals方法,对比的是地址
true
false
323. equals课堂练习3
输出:
true//表达式先转换到精度最大的类型即float,然后都是65.0,返回true(只有char、byte和short类型之间不能直接自动转换)
true//char转到精度更高的int,大写字母A的ASCII码是65
true//同上
false//不同的引用,地址不同
true//字符串内容相同
//不输出,类型不相同,编译器报错
324. hashCode
-
提高具有哈希结构的容器的效率!
-
两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
-
两个引用,如果指向的是不同对象,则哈希值一般(有可能在很大的范围内有碰撞)是不一样的
-
哈希值主要根据地址号来的!, 不能完全将哈希值等价于地址。
-
案例演示[HashCode_.java]: obj.hashCode() [测试:A obj1 = new A(); A obj2 = new A(); A obj3 = obj1]
-
后面在集合,中 hashCode 如果需要的话,也会重写, 在讲解集合时,老韩在说如何重写 hashCode()代码
325. toString
- 基本介绍
默认返回:全类名+@+哈希值的十六进制,【查看 Object 的 toString 方法】
子类往往重写 toString 方法,用于返回对象的属性信息 - 重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式.
案例演示:Monster [name, job, sal] 案例: ToString_.java - 当直接输出一个对象时,toString 方法会被默认的调用, 比如 System.out.println(monster); 就会默认调用
monster.toString()
326. finalize
- 当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法,做一些释放资源的操作【演示】
- 什么时候被回收:当某个对象没有任何引用时,则 jvm 就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来
销毁该对象,在销毁该对象前,会先调用 finalize 方法。 - 垃圾回收机制的调用,是由系统来决定(即有自己的 GC 算法), 也可以通过 System.gc() 主动触发垃圾回收机制,测
试:Car [name]
老韩提示: 我们在实际开发中,几乎不会运用 finalize , 所以更多就是为了应付面试.