Inheritance and Polymorphism of JAVA Class
The content included is not comprehensive. Some simple inheritance grammars in the front are skipped, and some unintelligible places are mainly recorded. Reference book: "Java Core Technology Volume I"
1. Correctly understand polymorphism
An object variable can indicate a variety of actual types of phenomenon called polymorphism (polymorphism), can automatically select the appropriate method at runtime, called dynamic binding (dynamic binding).
There are three elements to polymorphism:
- There must be an inheritance relationship
- There must be subclasses that override the parent class member methods
- There must be a parent data type to refer to a subclass
After polymorphism, the parent data type cannot use the unique properties and methods of the subclass .
For chestnut, Manager
class is employee
a subclass of class overrides the getSalary
method, so as the employee
type of staff[0]
call getSalary
is to exhibit a polymorphism, but staff[0]
can not call Manager
the class-specific methods.
public class helloworld {
public static void main(String[] args) {
employee[] staff = new employee[3];
staff[0] = new Manager("Jack", 5000, 2015, 10, 25, 2000);
staff[1] = new employee("Bob", 3000, 2017, 8, 7);
staff[2] = new employee("Alice", 2000, 2018, 11, 25);
for(employee e:staff){
System.out.println(e.getName() + "'s salary:"+e.getSalary());
}
}
}
Regarding **override (override)**, it is worth noting that the visibility of subclass methods cannot be lower than that of superclass methods!
For example, the superclass method is public, and the subclass method must also be declared as public.
2. Forced type conversion
Every object variable has a type. When a value is stored in the variable, the compiler will check whether you promise too much.
If a reference of a subclass is assigned to a superclass variable, the compiler allows it (such as the polymorphic chestnut above), but when a reference of a superclass is assigned to a subclass variable, too much promise. Must be forced type conversion.
There are two points to note:
- Coercion can only be performed within the inheritance hierarchy
- Casts may fail, so before making cast requires
instanceof
operator detects
public class helloworld {
public static void main(String[] args) {
employee staff = new employee("Bob", 3000, 2017, 8, 7);;
if(staff instanceof Manager){
// 判断是否能够转换
Manager boss = (Manager) staff; // 如果可以就进行转换
boss.show();
}
}
}
3. Final classes and methods
Sometimes, we don't want a certain class to define a subclass. This kind of class that does not allow extension is called a final class. We only need to use the final modifier when defining the class.
Similarly, if you don't want the methods in the class to be overridden, we can also use the final modifier when defining the method, but this will destroy polymorphism (of course many programmers feel that polymorphism is not needed).
4. Abstract class
Generally speaking, the upper class is more general and may be more abstract. From a certain point of view, the ancestor class is more general. People generally only use it as a base class to derive other classes, not to construct desired the specific example , which is an abstract class!
For example, we build an abstract class for people Person
, we will put on some common attributes of high-level abstract class, such as name name
; then we add a getDescription
method for obtaining a description of the person, but taking into account the need to adopt concrete subclasses different forms of description, we can not define this method, so that subclasses override this method, then you need to use abstract
keywords.
public abstract class Person {
private final String name;
public Person(String name){
this.name = name;
}
public abstract void getDescription();
public String getName(){
return this.name;
}
}
And, the class itself containing one or more abstract methods must be declared as abstract
Then we will be able to inherit the abstract class defines a subclass (note must override all the abstract
methods, or sub-category is still abstract!)
public class Employee extends Person {
// 员工类
private double salary;
public Employee(String name, double salary){
super(name);
this.salary = salary;
}
public void getDescription(){
// 重写抽象方法
System.out.println(super.getName() + " is an employee with a salary of " + this.salary + "$");
}
}
public class Student extends Person{
// 学生类
private String major;
public Student(String name, String major){
super(name);
this.major = major;
}
public void getDescription(){
// 重写抽象方法
System.out.println(super.getName() + " is a student majoring in " + this.major);
}
}
In this way, we have defined two concrete subclasses based on the abstract class!
Abstract classes cannot create object instances, but we can define abstract class variables to refer to objects of non-abstract subclasses, for example:
public class helloworld {
public static void main(String[] args) {
// 抽象类变量引用非抽象子类对象
Person a = new Student("Alice", "compute science");
a.getDescription();
}
}
5. Super class of all classes: Object
Object class is the super class of all classes in Java
5.1 equals method
The equals method in the Object class is used to detect whether an object is equal to another object, and its implementation method is to determine whether the references of two objects are equal . But we often need to detect the equality of objects based on their state . If two objects are in the same state, they are considered equal.
Therefore, we need to rewrite the equals method inherited from Object. But before that, I need to distinguish ==
the euquals
difference.
- For the basic type (char, boolean, byte, short , int, long, float, double) , it is not an object, you can not use the
equals
method, which is stored in the constant pool, using==
the determination time to time is determined from the value. - For general objects stored in the heap, when used
==
when determination is judged whether the in-memory heap address are equal, whereas whenequals
the time for judgment, calls the class defined in theequals
method to determine if weight is not a class writeequals
method, it will call its superclassequals
method for all types of the superclass: Object, itsequals
approach is==
, here is its source. (Some predefined classes, such as String, has achieved a good state-basedequals
method)
- For basic types of packaging, it may be stored in the stack, may store the constant pool, its size is determined to
Integer
an example, which is [-128,127] in the range of the constant pool, storage beyond it In the pile, we can see the chestnut below very clearly.
public class helloworld {
public static void main(String[] args) {
Integer a = 127; // 存储在常量池中,使用==比较的是其值
Integer b = 127;
System.out.println(a == b); // 输出true
Integer c = 128; // 存储在堆中,使用==比较的是其堆地址
Integer d = 128;
System.out.println(c == d); // 输出false
// 使用equals方法,已预定义好,是比较其状态值(即其int值)
System.out.println(c.equals(d)); // 输出true
}
}
Understanding ==
and equals
after a difference, we can give our class overrides equals
the method, mainly because such an idea below (has an Employee class, for example).
...
public boolean equals(Object otherObject){
// 1.在开始比较之前,首先比较地址值,如果地址值相等就无需后续比较了
if(this == otherObject)
return true;
// 2.判断是否为空,非常重要!否则容易引发异常
if(otherObject == null)
return false;
// 3.如果由子类决定相等性概念,我们就使用getClass来进行判断
if(this.getClass() != otherObject.getClass())
return false;
//3*.如果由超类决定相等性概念,我们就使用instanceof来进行判断
//if(!(otherObject instanceof Employee))
// return false;
// 类型转换
Employee other = (Employee) otherObject;
// 4.进行状态比较
return Objects.equals(other.getName(), this.getName()) && other.salary == this.salary;
}
...
Let's test it briefly:
public class helloworld {
public static void main(String[] args) {
Employee a = new Employee("Bob", 2000);
Employee b = new Employee("Bob", 2000);
System.out.println(a.equals(b)); // true
System.out.println(a == b); // false
}
}
That's it~
5.2 hashCode method
How to get the hash code
The hashCode method is defined in Object, and its value is derived from its storage address , and the hash value we usually need is derived based on its content , so we need to rewrite it when creating a class.
The hashCode method has been rewritten in some predefined classes, such as the String class:
int hash = 0;
for(int hash = 0; i < length(); i++)
hash = 31 * hash + charAt(i);
What about the classes that we define ourselves?
Our custom classes are generally composed of basic data types and some predefined classes, so we only need to combine their hashCode.
Look directly at the following code, or take the Employee class as an example:
...
public int hashCode(){
// 使用预定义类Double和String的hashCode函数生成新的hashCode
return 7 * Double.hashCode(this.salary) + 9 * Objects.hashCode(this.getName());
}
...
Then try the hashCode we implemented
public class helloworld {
public static void main(String[] args) {
Employee a = new Employee("Bob", 2000);
Employee b = new Employee("Bob", 2000);
System.out.println(a.hashCode()); // 查看a的hashCode
System.out.println(a.hashCode() == b.hashCode()); // true 成功实现基于内容的hashCode
}
}
great!
5.3 toString method
There is also a very important method in Object:, toString
the default method is as follows:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
When we want to print a LocalDate class, we can easily write the following code:
LocalDate now = LocalDate.now();
System.out.println("现在时间是" + now);
We know that only the string String can simply perform the "+" operation, but why does LocalDate also work?
And strings together because, Java compiler will automatically call as long as an object by its operator "+" toString
method, it is very convenient to use.
For these predefined classes, have rewritten a good toString
way for our custom classes you need to rewrite our own, most of the toString
methods followed this format: name of the class, then when a pair of square brackets The field value.
In the above code, take the Employee class as an example:
...
public String toString(){
return this.getClass()+"[name="+this.getName()+",salary="+this.salary+"]";
}
...
Try it~
public class helloworld {
public static void main(String[] args) {
Employee a = new Employee("Bob", 2000);
System.out.println(a.toString());
}
}
Output result:
class com.panfeng.Employee[name=Bob,salary=2000.0]
Not bad~