Object oriented foundation of Java

Object oriented programming, as the name suggests, you have to have an object first; With the object, you can interact with the object; It is a programming method that maps the real world to the computer model by means of objects.

catalogue

1, Method
2, Construction method
3, Method overloading
4, Inherit
5, Polymorphism
6, Abstract class
7, Interface
8, Static fields and static methods
9, Package
10, Scope
11, Inner class
12, classpath and jar
Thirteen, module

1, Method

Return to top directory

1. Definition method

Modifier method return type method name(Method parameter list) {
    Several method statements;
    return Method return value;
}

The return value of the method is realized through the return statement. If there is no return value and the return type is set to void, return can be omitted.

2,private

Methods and fields decorated with private can only work in this class
Usually, we will modify the field with private and indirectly access the field in this class with non private modification methods

3. this variable

Inside the method, you can use an implicit variable this, which always points to the current instance. Therefore, through this Field to access the fields of the current instance.

class Person {
    private String name;

    public void setName(String name) {
        this.name = name; // The previous this is indispensable. If it is missing, it will become the local variable name
    }
}

2, Construction method

Return to top directory

When you create an instance, you actually initialize the instance by constructing a method. Let's first define a construction method. When creating a Person instance, we can pass in name and age at one time to complete initialization:

public class Main {
    public static void main(String[] args) {
        Person p = new Person("Xiao Ming", 15);
        System.out.println(p.getName());
        System.out.println(p.getAge());
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return this.name;
    }

    public int getAge() {
        return this.age;
    }
}

If a class does not have a constructor defined, the compiler will automatically generate a default constructor for us. It has no parameters and no execution statements, like this:

class Person {
    public Person() {
    }
}

3, Method overloading

Return to top directory

In a class, we can define multiple methods. If there are a series of methods with similar functions and different parameters, you can make this group of method names into methods with the same name. For example, in the Hello class, define multiple hello() methods:

class Hello {
    public void hello() {
        System.out.println("Hello, world!");
    }

    public void hello(String name) {
        System.out.println("Hello, " + name + "!");
    }

    public void hello(String name, int age) {
        if (age < 18) {
            System.out.println("Hi, " + name + "!");
        } else {
            System.out.println("Hello, " + name + "!");
        }
    }
}

This method has the same name but different parameters. It is called method Overload.

4, Inherit

Return to top directory

Through inheritance, you only need to write additional functions and no longer need to repeat code.

Note: the subclass automatically obtains all fields of the parent class. It is strictly prohibited to define fields with the same name as the parent class!

1. Inheritance tree

In Java, if the class of extends is not explicitly written, the compiler will automatically add extends Object. Therefore, any class, except Object, will inherit from a class.

Java allows only one class to inherit from one class, so a class has and only has one parent class. Only Object is special. It has no parent class.

2,protected

Inheritance has a feature that subclasses cannot access the private field or private method of the parent class. For example, the Student class cannot access the name and age fields of the Person class:

class Person {
    private String name;
    private int age;
}

class Student extends Person {
    public String hello() {
        return "Hello, " + name; // Compilation error: unable to access the name field
    }
}

This weakens the role of inheritance. In order for the subclass to access the fields of the parent class, we need to change private to protected. Fields decorated with protected can be accessed by subclasses:

class Person {
    protected String name;
    protected int age;
}

class Student extends Person {
    public String hello() {
        return "Hello, " + name; // OK!
    }
}

Therefore, the protected keyword can control the access rights of fields and methods within the inheritance tree. A protected field and method can be accessed by its subclasses and subclasses of subclasses.

3,super

Super keyword indicates the parent class (superclass). When a subclass references a field of a parent class, you can use super fieldName. For example:

class Student extends Person {
    public String hello() {
        return "Hello, " + super.name;
    }
}

In fact, super is used here Name, or this Name, or name, has the same effect. The compiler will automatically navigate to the name field of the parent class.

However, in some cases, super must be used. Let's take an example:

public class Main {
    public static void main(String[] args) {
        Student s = new Student("Xiao Ming", 12, 89);
    }
}

class Person {
    protected String name;
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        this.score = score;
    }
}

Running the above code will get a compilation error to the effect that the constructor of Person cannot be called in the constructor of Student.

This is because in Java, the first line of any class constructor must call the constructor of the parent class. If we don't explicitly call the constructor of the parent class, the compiler will automatically add a super();, Therefore, the construction method of Student class is actually as follows:

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        super(); // Automatically call the constructor of the parent class
        this.score = score;
    }
}

However, the Person class does not have a parameterless constructor, so compilation fails.

The solution is to call a constructor existing in the Person class. For example:

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        super(name, age); // Call the constructor Person(String, int) of the parent class
        this.score = score;
    }
}

Therefore, we conclude that if the parent class does not have a default constructor, the child class must explicitly call super() and give parameters so that the compiler can locate an appropriate constructor of the parent class.

This also leads to another problem: that is, the subclass will not inherit the constructor of any parent class. The default construction method of subclasses is automatically generated by the compiler, not inherited.

4. Block inheritance

Under normal circumstances, as long as a class has no final modifier, any class can inherit from that class.

Starting from Java 15, it is allowed to use sealed to modify the class, and write out the subclass name that can be inherited from the class through permissions.

For example, define a Shape class:

public sealed class Shape permits Rect, Circle, Triangle {
    ...
}

The above Shape class is a sealed class, which only allows the specified three classes to inherit it.

5. Upward transformation

Inheritance tree student > person > object

Person p = new Student(); // ???

Student inherits from Person, so it has all the functions of Person. If a variable of Person type points to an instance of student type, there is no problem operating on it!

This assignment that safely changes a subclass type into a parent type is called upcasting.
The upward transformation is actually to safely change a subtype into a more abstract parent type

6. Downward transformation

Contrary to the upward transformation, if a parent type is forcibly transformed into a child type, it is downward casting. For example:

Person p1 = new Student(); // upcasting, ok
Person p2 = new Person();
Student s1 = (Student) p1; // ok
Student s2 = (Student) p2; // runtime error! ClassCastException!

If you test the above code, you can find:

Person type p1 actually points to the Student instance, and person type variable p2 actually points to the person instance. During the downward transformation, the transformation from p1 to Student will succeed, because p1 does point to the Student instance, and the transformation from p2 to Student will fail, because the actual type of p2 is person, and the parent class cannot be changed into a child class, because the child class has more functions than the parent class, and more functions cannot be changed out of thin air.

Therefore, the downward transformation is likely to fail. In case of failure, the Java virtual opportunity reports ClassCastException.

Contrary to upward transformation, if a parent type is forcibly transformed into a child type, it is downward casting
In order to avoid downward transformation errors, Java provides an instanceof operator. Instanceof actually determines whether the instance pointed to by a variable is a specified type or a subclass of this type. If a reference variable is null, the judgment of any instanceof is false.

Using instanceof, you can judge before the downward Transformation:

Person p = new Student();
if (p instanceof Student) {
    // Only by judging success can we transition downward:
    Student s = (Student) p; // It will succeed
}

Starting from Java 14, after judging instanceof, it can be directly transformed into a specified variable to avoid forced transformation again. For example, for the following code:

Object obj = "hello";
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.toUpperCase());
}

7. Inheritance and composition

Student can hold a Book instance instead of inheriting from book. Student should inherit from Person:

class Student extends Person {
    protected Book book;
    protected int score;
}

8. Method rewrite rule

1. The method names of parent and child classes are the same
2. The method parameter list of parent and child classes is the same (quantity, location, data type and parameter name are not required)
3. The return value of the subclass method is the same as the return value of the parent method or its subclass
4. The access permission of a subclass method cannot be less than that of the parent class
Public > protected > Default > private

5, Polymorphism

Return to top directory

A thing has many forms, that is, polymorphism.

Define a method to present different business logic according to different requirements in a specific production environment.

Business: Bookstore members buy books, and ordinary members and super members have different preferential levels

package com.test3;

public class OrdinaryMember {
    public void buyBook(){
        System.out.println("10% off books for ordinary members");
    }
}
package com.test3;

public class SuperMember {
    public void buyBook(){
        System.out.println("Super members get a 60% discount on books");
    }
}
package com.test3;

public class Cashier {
    private SuperMember superMember;

    public SuperMember getSuperMember() {
        return superMember;
    }

    public void setSuperMember(SuperMember superMember) {
        this.superMember = superMember;
    }

    public void settlement(){
        System.out.println("check");
        this.superMember.buyBook();
    }
}
package com.test3;

public class Test {
    public static void main(String[] args) {
        SuperMember superMember = new SuperMember();
        Cashier cashier = new Cashier();
        cashier.setSuperMember(superMember);
        cashier.settlement();
    }
}

Modify using polymorphism

package com.test3;

public class Member {
    public void buyBook(){

    }
}
package com.test3;

public class Cashier {
    private Member member;

    public Member getMember() {
        return member;
    }

    public void setMember(Member member) {
        this.member = member;
    }

    public void settlement(){
        System.out.println("check");
        this.member.buyBook();
    }
}
package com.test3;

public class Test {
    public static void main(String[] args) {
//        OrdinaryMember member = new OrdinaryMember();
//        SuperMember member = new SuperMember();
        VIPMember member = new VIPMember();
        Cashier cashier = new Cashier();
        cashier.setMember(member);
        cashier.settlement();
    }
}

Inheritance is the basis of polymorphism. The parent type is written in the code, and the subclass object is passed in when it is really used.

Use of polymorphism

1. When defining a method, the formal parameter is the parent type, and the parameter passed in when calling the method is the subclass object.

public class Cashier {
    public void settlement(Member member){
        System.out.println("check");
        member.buyBook();
    }
}
Member member = new VIPMember();
Cashier cashier = new Cashier();
cashier.settlement(member);

2. When defining a method, the return value type is the parent class, and when calling a method, the child class object is returned.

public Member getMember(String name){
    if(name.equals("ordinaryMember")){
        return new OrdinaryMember();
    }else{
        return new SuperMember();
    }
}
Cashier cashier = new Cashier();
System.out.println(cashier.getMember("ordinaryMember"));
System.out.println(cashier.getMember("superMember"));

6, Abstract class

Return to top directory

A method without a method body is called an abstract method. To declare an abstract method, you need to add the abstract keyword.

public abstract void buyBook();

Once an abstract method is defined in a class, the class must also be declared as an abstract class, and the abstract keyword must be added to the class definition.

public abstract class Member {
    public abstract void buyBook();
}

The difference between abstract classes and ordinary classes is that abstract classes cannot be instantiated. The difference between abstract methods and ordinary methods is that abstract methods have no method body.

There can be no abstract methods in an abstract class, but the class containing the abstract methods must be an abstract class.

Polymorphism is a programming idea. An abstract concept is defined in a class and programmed. When it is actually used, it is given different specific objects according to different situations, so as to complete different businesses. This is the idea of polymorphism.

Abstract classes and abstract methods are used to implement polymorphic concrete forms. Abstract concepts are abstract classes, and abstract methods are methods in abstract classes that need to be rewritten by subclasses.

The characteristics of object-oriented programming: encapsulation, inheritance, polymorphism and abstraction

7, Interface

Return to top directory

In abstract classes, abstract methods essentially define interface specifications: that is, specify the interface of high-level classes, so as to ensure that all subclasses have the same interface implementation. In this way, polymorphism can exert its power.

If an abstract class has no fields, all methods are abstract methods:

abstract class Person {
    public abstract void run();
    public abstract String getName();
}

You can rewrite the abstract class as an interface: interface.
In Java, you can declare an interface by using interface:

interface Person {
    void run();
    String getName();
}

The so-called interface is a pure abstract interface that is more abstract than an abstract class, because it can't even have fields. Because all methods defined by the interface are public abstract by default, these two modifiers do not need to be written (the effect is the same whether they are written or not).

When a specific class implements an interface, you need to use the implements keyword. for instance:

class Student implements Person {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(this.name + " run");
    }

    @Override
    public String getName() {
        return this.name;
    }
}

We know that in Java, a class can only inherit from another class, not from multiple classes. However, a class can implement multiple interface s, for example:

class Student implements Person, Hello { // Two interface s are implemented
}

8, Static fields and static methods

Return to top directory

1. Static field

The instance field has its own independent "space" in each instance, but the static field has only one shared "space", which will be shared by all instances. for instance:

class Person {
    public String name;
    public int age;
    // Define static field number:
    public static int number;
}

Let's look at the following code:

public class Main {
    public static void main(String[] args) {
        Person ming = new Person("Xiao Ming", 12);
        Person hong = new Person("Xiao Hong", 15);
        ming.number = 88;
        System.out.println(hong.number);
        hong.number = 99;
        System.out.println(ming.number);
    }
}

class Person {
    public String name;
    public int age;

    public static int number;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

For static fields, no matter which instance's static fields are modified, the effect is the same: the static fields of all instances are modified because the static fields do not belong to instances:


Although instances can access static fields, they actually point to static fields of Person class. Therefore, all instances share a static field.

Therefore, instance variables are not recommended Static fields to access static fields, because in Java programs, instance objects do not have static fields. In code, instance objects can access static fields only because the compiler can automatically convert them to class names according to the instance type Static fields to access static objects.

It is recommended to use the class name to access static fields. Static fields can be understood as fields describing the class itself (non instance fields). For the above code, the better way to write it is:

Person.number = 99;
System.out.println(Person.number);

2. Static method

If there are static fields, there are static methods. Methods modified with static are called static methods.

Calling an instance method must pass through an instance variable, while calling a static method does not need an instance variable and can be called through the class name. Static methods are similar to functions in other programming languages. For example:

public class Main {
    public static void main(String[] args) {
        Person.setNumber(99);
        System.out.println(Person.number);
    }
}

class Person {
    public static int number;

    public static void setNumber(int value) {
        number = value;
    }
}

Because the static method belongs to class rather than instance, it cannot access this variable or instance field inside the static method. It can only access static fields.

Static methods can also be called through instance variables, but this is just that the compiler automatically rewrites the instance into a class name.

In general, accessing static fields and static methods through instance variables will get a compilation warning.

Static methods are often used in tool classes. For example:

Arrays.sort()

Math.random()

Static methods are also often used as auxiliary methods. Notice that the Java program entry main() is also a static method.

3. Static field of interface

Because interface is a pure abstract class, it cannot define instance fields. However, the interface can have static fields, and the static fields must be final:

public interface Person {
    public static final int MALE = 1;
    public static final int FEMALE = 2;
}

In fact, because the field of interface can only be public static final, we can remove these modifiers. The above code can be abbreviated as:

public interface Person {
    // The compiler will automatically add public statc final:
    int MALE = 1;
    int FEMALE = 2;
}

The compiler will automatically change this field to public static final type.

9, Package

Return to top directory

The package mechanism built in Java is to avoid class naming conflict;

The core class of JDK uses Java Lang package, the compiler will import it automatically;

Other common classes of JDK are defined in Java util., java.math., java.text.*,……;

Inverted domain names are recommended for package names, such as org apache.

10, Scope

Return to top directory The built-in access permissions of Java include public, protected, private and package permissions;

Variables defined in Java methods are local variables. The scope of local variables starts from variable declaration to the end of a block;

The final modifier is not an access right. It can modify class, field and method;

One java files can only contain one public class, but can contain multiple non-public classes.

11, Inner class

Return to top directory

1,Inner Class

If a class is defined inside another class, this class is Inner Class:

class Outer {
    class Inner {
        // An Inner Class is defined
    }
}

The Outer Class defined above is an ordinary class, while the Inner Class is an Inner Class. The biggest difference between it and an ordinary class is that the instance of Inner Class cannot exist alone and must be attached to an instance of Outer Class. The example code is as follows:

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer("Nested"); // Instantiate an Outer
        Outer.Inner inner = outer.new Inner(); // Instantiate an Inner
        inner.hello();
    }
}

class Outer {
    private String name;

    Outer(String name) {
        this.name = name;
    }

    class Inner {
        void hello() {
            System.out.println("Hello, " + Outer.this.name);
        }
    }
}

To observe the above code, to instantiate a Inner, we must first create an instance of Outer, and then invoke the new of Outer instance to create Inner instance:

Outer.Inner inner = outer.new Inner();

This is because the Inner Class not only has a this pointing to itself, but also implicitly holds an Outer Class instance. You can use Outer This accesses this instance. Therefore, instantiating an Inner Class cannot be separated from the Outer instance.

Compared with ordinary classes, Inner Class has an additional "privilege" besides being able to reference Outer instances, that is, it can modify the private field of Outer Class. Because the scope of Inner Class is within Outer Class, it can access the private field and method of Outer Class.

Observe the Java compiler after compiling The class file shows that the Outer class is compiled as Outer Class, and the Inner class is compiled as Outer $Inner class.

2,Anonymous Class

There is also a method to define the Inner Class. It does not need to explicitly define this Class in the Outer Class, but is defined inside the method through the Anonymous Class. The example code is as follows:

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer("Nested");
        outer.asyncHello();
    }
}

class Outer {
    private String name;

    Outer(String name) {
        this.name = name;
    }

    void asyncHello() {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello, " + Outer.this.name);
            }
        };
        new Thread(r).start();
    }
}

Looking at the asyncHello() method, we instantiate a runnable inside the method. Runnable itself is an interface, which cannot be instantiated. Therefore, an anonymous class that implements the runnable interface is actually defined here, and the anonymous class is instantiated through new, and then transformed into runnable. When defining an anonymous class, you must instantiate it. The writing method of defining an anonymous class is as follows:

Runnable r = new Runnable() {
    // Implement the necessary abstract methods
};

Anonymous classes, like inner classes, can access the private fields and methods of outer classes. The reason why we want to define an anonymous class is that we usually don't care about the class name here. We can write a lot less code than directly defining Inner Class.

Observe the Java compiler after compiling The class file shows that the outer class is compiled as outer Class. Outer is compiled anonymously, while $1 is compiled anonymously class. If there are multiple anonymous classes, the Java compiler will name each anonymous class Outer , Outer,, Outer in turn

In addition to interfaces, anonymous classes can also inherit from ordinary classes. Observe the following codes:

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        HashMap<String, String> map1 = new HashMap<>();
        HashMap<String, String> map2 = new HashMap<>() {}; // Anonymous class!
        HashMap<String, String> map3 = new HashMap<>() {
            {
                put("A", "1");
                put("B", "2");
            }
        };
        System.out.println(map3.get("A"));
    }
}

map1 is an ordinary HashMap instance, but map2 is an anonymous class instance, which inherits from HashMap. map3 is also an anonymous class instance inherited from HashMap, and a static code block is added to initialize the data. Observe the compiled output and find main $1 Class and main $2 Class two anonymous class files.

3,Static Nested Class

The last internal class is similar to the Inner Class, but is modified with static, which is called Static Nested Class:

public class Main {
    public static void main(String[] args) {
        Outer.StaticNested sn = new Outer.StaticNested();
        sn.hello();
    }
}

class Outer {
    private static String NAME = "OUTER";

    private String name;

    Outer(String name) {
        this.name = name;
    }

    static class StaticNested {
        void hello() {
            System.out.println("Hello, " + Outer.NAME);
        }
    }
}

The Inner Class decorated with static is very different from the Inner Class. It is no longer attached to the instance of Outer, but a completely independent class. Therefore, Outer cannot be referenced This, but it can access Outer's private static fields and static methods. If you move StaticNested outside of Outer, you lose access to private.

12, classpath and jar

Return to top directory The JVM determines the path and order of searching classes through the environment variable classpath;

Setting the system environment variable classpath is not recommended. It is always recommended to pass it in through the - cp command;
The jar package is equivalent to a directory and can contain many class file, easy to download and use;

MANIFEST.MF file can provide jar package information, such as main class, so that jar package can be run directly

Thirteen, module

Return to top directory The module introduced by Java 9 is to manage dependencies;

JRE can be packaged as required by using the module;

There are further restrictions on the access to the class using the module.

reference resources
Liao Xuefeng

Keywords: Java

Added by JeanieTallis on Wed, 23 Feb 2022 16:49:56 +0200