Home  >  Article  >  Java  >  Java: Classes and Inheritance

Java: Classes and Inheritance

高洛峰
高洛峰Original
2017-02-08 11:05:191373browse

For object-oriented programming languages, classes are undoubtedly the most important foundation. The four major features of abstraction, encapsulation, inheritance, and polymorphism are inseparable from classes. Only the existence of classes can reflect the characteristics of object-oriented programming. Today we will learn some knowledge about classes and inheritance. First, let's talk about things related to the initialization of classes, and then we will explain the great feature of inheritance from several aspects. The following is the table of contents outline of this article:

1. Do you understand classes?

2. Do you understand inheritance?

3. Common written interview questions

1. Do you understand categories?

In Java, a class file is a code file with the suffix .java. Only one public class is allowed to appear in each class file. When there is a public class, the name of the class file must be the same as public. The names of the classes are the same. If there is no public, the name of the class file can be any name (of course, names starting with numbers are not allowed).

Within the class, for member variables, if there is no explicit assignment initialization when defining, Java will ensure that each member variable of the class is properly initialized:

 1) For variables of basic data types such as char, short, byte, int, long, float, double, etc., they will be initialized to 0 by default (boolean variables will be initialized to false by default);

 2) For reference types Variables will be initialized to null by default.

If the constructor is not explicitly defined, the compiler will automatically create a no-argument constructor, but remember that if the constructor is explicitly defined, the compiler will not automatically add the constructor. Note that all constructors are static by default.

Next we focus on the initialization sequence:

When the program is executed, an object of a certain class needs to be generated. The Java execution engine will first check whether the class is loaded. If not, then The class is loaded first and then the object is generated. If it has been loaded, the object is generated directly.

During the loading process of the class, the static member variables of the class will be initialized. In addition, if there is a static statement block in the class, the static statement block will be executed. The execution order of static member variables and static statement blocks is consistent with the order in the code. Remember, in Java, classes are loaded on demand. This class will only be loaded when it is needed, and only once. Look at the following example to understand:

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
         
        Bread bread1 = new Bread();
        Bread bread2 = new Bread();
    }
}
 
 
class Bread {
    static{
        System.out.println("Bread is loaded");
    }
    public Bread() {
        System.out.println("bread");
    }
}

When you run this code, you will find that "Bread is loaded" will only be printed once.

During the process of generating an object, the member variables of the object will be initialized first, and then the constructor will be executed. This means that the variables in the class will be initialized before any method (including the constructor) is called, even if the variables are interspersed between method definitions.

public class Test {
    public static void main(String[] args)  {
        new Meal();
    }
}
 
 
class Meal {
     
    public Meal() {
        System.out.println("meal");
    }
     
    Bread bread = new Bread();
}
 
class Bread {
     
    public Bread() {
        System.out.println("bread");
    }
}

The output result is:

bread
meal

2. Do you understand inheritance?

Inheritance is an indispensable part of all OOP languages. The extends keyword is used in Java to express the inheritance relationship. When a class is created, it is always inherited. If the class to be inherited is not explicitly stated, it is always implicitly inherited from the root class Object. For example, the following code:

class Person {
    public Person() {
         
    }
}
 
class Man extends Person {
    public Man() {
         
    }
}

The class Man inherits from the Person class. In this case, the Person class is called the parent class (base class), and the Man class is called the subclass (derived class). If there is an inheritance relationship between two classes, the subclass will automatically inherit the methods and variables of the parent class, and the methods and variables of the parent class can be called in the subclass. In Java, only single inheritance is allowed, which means that a class can only explicitly inherit from at most one parent class. But a class can be inherited by multiple classes, which means that a class can have multiple subclasses.

 1. The subclass inherits the member variables of the parent class

When the subclass inherits a certain class, it can use the member variables in the parent class, but it does not completely inherit the parent class. All member variables. The specific principles are as follows:

1) The public and protected member variables of the parent class can be inherited; the private member variables of the parent class cannot be inherited;

2) The package access permission members of the parent class Variables, if the subclass and the parent class are in the same package, the subclass can inherit; otherwise, the subclass cannot inherit;

 3) For the parent class member variables that the subclass can inherit, if they are in the subclass If a member variable with the same name appears in the class, the hidden phenomenon will occur, that is, the member variable of the subclass will block the member variable of the parent class with the same name. If you want to access a member variable with the same name in the parent class in a subclass, you need to use the super keyword for reference.

 2. The subclass inherits the methods of the parent class

Similarly, the subclass does not completely inherit all the methods of the parent class.

1) Can inherit the public and protected member methods of the parent class; cannot inherit the private member methods of the parent class;

2) For the package access member methods of the parent class, if the subclass If it is in the same package as the parent class, the subclass can inherit; otherwise, the subclass cannot inherit;

  3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。

  注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。(后面会讲到)

  3.构造器

  子类是不能够继承父类的构造器,但是要注意的是,如果父类的构造器都是带有参数的,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super关键字调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。看下面这个例子就清楚了:

class Shape {
     
    protected String name;
     
    public Shape(){
        name = "shape";
    }
     
    public Shape(String name) {
        this.name = name;
    }
}
 
class Circle extends Shape {
     
    private double radius;
     
    public Circle() {
        radius = 0;
    }
     
    public Circle(double radius) {
        this.radius = radius;
    }
     
    public Circle(double radius,String name) {
        this.radius = radius;
        this.name = name;
    }
}

  这样的代码是没有问题的,如果把父类的无参构造器去掉,则下面的代码必然会出错:

Java: Classes and Inheritance

  改成下面这样就行了:

Java: Classes and Inheritance

  4.super

  super主要有两种用法:

  1)super.成员变量/super.成员方法;

  2)super(parameter1,parameter2....)

  第一种用法主要用来在子类中调用父类的同名成员变量或者方法;第二种主要用在子类的构造器中显示地调用父类的构造器,要注意的是,如果是用在子类构造器中,则必须是子类构造器的第一个语句。

三.常见的面试笔试题

1.下面这段代码的输出结果是什么?

public class Test {
    public static void main(String[] args)  {
        new Circle();
    }
}
 
class Draw {
     
    public Draw(String type) {
        System.out.println(type+" draw constructor");
    }
}
 
class Shape {
    private Draw draw = new Draw("shape");
     
    public Shape(){
        System.out.println("shape constructor");
    }
}
 
class Circle extends Shape {
    private Draw draw = new Draw("circle");
    public Circle() {
        System.out.println("circle constructor");
    }
}

shape draw constructor
shape constructor
circle draw constructor
circle constructor

  这道题目主要考察的是类继承时构造器的调用顺序和初始化顺序。要记住一点:父类的构造器调用以及初始化过程一定在子类的前面。由于Circle类的父类是Shape类,所以Shape类先进行初始化,然后再执行Shape类的构造器。接着才是对子类Circle进行初始化,最后执行Circle的构造器。

2.下面这段代码的输出结果是什么?

public class Test {
    public static void main(String[] args)  {
        Shape shape = new Circle();
        System.out.println(shape.name);
        shape.printType();
        shape.printName();
    }
}
 
class Shape {
    public String name = "shape";
     
    public Shape(){
        System.out.println("shape constructor");
    }
     
    public void printType() {
        System.out.println("this is shape");
    }
     
    public static void printName() {
        System.out.println("shape");
    }
}
 
class Circle extends Shape {
    public String name = "circle";
     
    public Circle() {
        System.out.println("circle constructor");
    }
     
    public void printType() {
        System.out.println("this is circle");
    }
     
    public static void printName() {
        System.out.println("circle");
    }
}

shape constructor
circle constructor
shapethis is circle
shape

  这道题主要考察了隐藏和覆盖的区别(当然也和多态相关,在后续博文中会继续讲到)。

  覆盖只针对非静态方法(终态方法不能被继承,所以就存在覆盖一说了),而隐藏是针对成员变量和静态方法的。这2者之间的区别是:覆盖受RTTI(Runtime type  identification)约束的,而隐藏却不受该约束。也就是说只有覆盖方法才会进行动态绑定,而隐藏是不会发生动态绑定的。在Java中,除了static方法和final方法,其他所有的方法都是动态绑定。因此,就会出现上面的输出结果。

更多Java: Classes and Inheritance相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn