Day13 internal class and various methods in common class Object

Posted by halex on Thu, 20 Jan 2022 13:45:57 +0100

Internal class:

Definition of inner class: defining a class inside other classes is called inner class

Features of internal classes:
1. Internal classes can access members of external classes, including private classes
2. If an external class wants to access the members of an internal class, it must create an object of the internal class

According to the different positions of the internal class defined in the class, it can be divided into the following two formats:

Member location (member inner class)

Local location (local inner class)

Member inner class:

1. Defined on the member location of the class

2. Inner classes can be members of outer classes, including private methods

Create the format of the inner class correctly:

External class name Member internal class name object name = new external class name () New member internal class name ();

class Outer3{
    private int num = 10;

    class Inner{
        public void show(){
            System.out.println(num);
        }
    }
}


public class InnerClassDemo3 {
    public static void main(String[] args) {
        //External class name Member internal class name object name = new external class name () New member internal class name ();
//        Outer3.Inner oi3 = new Outer3().new Inner();
//        oi3.show();

        Outer3 outer3 = new Outer3();
        Outer3.Inner inner = outer3.new Inner();
        inner.show();
        }
}

Common modifiers for member inner classes:

Private: other classes cannot directly create objects of internal classes. If you want to modify internal class members with private, you must indirectly create object calls in this class

Static: if the inner class is modified by satic, only static members in the outer class can be accessed

When inner classes are statically decorated, there is another way to create inner classes

The format is as follows: external class name Internal class name object name = new external class name Internal class name ();

Access cases in internal classes:

class Outer2{
    public int num=10;
        class Inner2{
            public int num=20;
            public void fun(){
                int num=30;
                System.out.println(num);
//                Output 30
                System.out.println(this.num);
//                Access num in this class. Output 20
//                There are two ways to access member num in Outer:
                System.out.println(new Outer2().num);
//                Access num in Outer2 by creating an object. Output 10
//                super cannot be used here because Outer2 and Inner2 are not inherited
                System.out.println(Outer2.this.num);
//                By accessing this. In Outer Num, also output 10
            }
        }
}
public class Test2Demo {
    public static void main(String[] args) {
        Outer2.Inner2 inner=new Outer2().new Inner2();
        inner.fun();
    }
}

Local inner class:

1. Classes defined in methods

2. A local inner class can directly method all members of an outer class

3. To use methods in a local inner class, create a local inner class object and call the method in the member method that defines the local inner class.

class Out{
    private int num=10;

    public void fun(){
        int num2=20;
        class Inner{
            int num=30;
            public void show(){
                System.out.println(num);
                System.out.println(num2);
//                num2=34; It cannot be modified here
//        The local variable referenced in the local inner class must be the final variable or the actual final variable
//    Through the observation of decompilation tool, it is found that the local variables defined in the methods with local internal classes are automatically added with the final keyword
                //At jdk1 After 8, the final keyword will be added automatically
                num=44;
                System.out.println(num);
            }
        }
        Inner i=new Inner();
        i.show();
    }

}
public class Test3Demo {
    public static void main(String[] args) {
        Out o=new Out();
        o.fun();
    }
}

The local variable referenced in the local inner class must be the final variable or the actual final variable

Through the observation of decompilation tool, it is found that the local variables defined in the methods with local internal classes are automatically added with the final keyword

At jdk1 After 8, the final keyword will be added automatically

Anonymous inner class:

Statement definition format:

new class name (can be abstract or concrete) / interface (){

The method to override;

};

The premise for the existence of anonymous internal classes: there should be a class or an interface. This class can be either a concrete class or an abstract class

Use of anonymous inner classes:

interface Inter {
    public abstract void show();
    public abstract void show2();
}

/*
  The initial approach is to define a class to implement the interface, and then use polymorphism to create objects and call methods
class B implements Inter{

    @Override
    public void show() {
        System.out.println("This is the show method "");
    }

    @Override
    public void show2() {
        System.out.println("This is the show2 method "");
    }
}
    Inter inter=new B();
*/

class Outer3{
    public void fun(){
//        Use anonymous inner classes to create objects and implement methods in the interface inter
        new Inter(){

            @Override
            public void show() {
                System.out.println("This is show method");
            }

            @Override
            public void show2() {
                System.out.println("This is show2 method");
            }
        }.show();
//        Create an object by using an anonymous inner class and call the show method
        new Inter(){

            @Override
            public void show() {
                System.out.println("This is show method");
            }

            @Override
            public void show2() {
                System.out.println("This is show2 method");
            }
        }.show2();
//        Use anonymous inner classes to create objects and call show2 method
//       When you need to use anonymous inner classes to call methods in the future, if there are many methods, you need to create a lot of space, which is very troublesome. Therefore, give the anonymous inner class a name
//        Use the form of interface polymorphism to name
        Inter inter = new Inter() {
            @Override
            public void show() {
                System.out.println("This is show method");
            }

            @Override
            public void show2() {
                System.out.println("This is show2 method");
            }
        };
        inter.show();
        inter.show2();
    }
}
public class Test4Demo {
    public static void main(String[] args) {
        Outer3 outer3=new Outer3();
        outer3.fun();
    }
}

Use of anonymous inner classes in development:

interface Human{
    public abstract void sleep();
}

class Man{
    Human human;

    public Man() {
    }

    public Man(Human human) {
        this.human = human;
    }
    public void run(Human human){
        human.sleep();
    }
}

public class Test5Demo {
    public static void main(String[] args) {
//        Use anonymous inner classes to create objects and implement interfaces, and call sleep
        Human human =new Human(){

            @Override
            public void sleep() {
                System.out.println("Break your sleep quickly. Life matters");
            }
        };
        human.sleep();
//        Use anonymous inner class objects to pass parameters (construct methods to create objects and call run methods)
        Man man= new Man(new Human(){

            @Override
            public void sleep() {
                System.out.println("This is the construction method with parameters");
            }
        });
        man.run(new Human() {
            @Override
            public void sleep() {
                System.out.println("Break your sleep quickly. Life matters");
            }
        });
//        Improvement: objects are still created using parameterized constructs, but using chained programming:
        new Man(new Human(){

            @Override
            public void sleep() {
                System.out.println("This is the construction method with parameters");
            }
        }).run(new Human() {
            @Override
            public void sleep() {
                System.out.println("Break your sleep quickly. Life matters");
            }
        });
//        Another way to write: access the sleep method through the member variable in the Man class
        new Man(new Human() {
            @Override
            public void sleep() {
                System.out.println("This is the construction method with parameters");
            }
        }).human.sleep();

    }
}

Examples of anonymous inner classes:

 interface Inter {

        void show();

}

class Outer {

/ / supplement the code

}

class OuterDemo {

        public static void main(String[] args) {

                Outer.method().show();

                 }

}"HelloWorld" is required to be output on the console

Analysis:

1. The first conclusion is derived from the code of main method call: method() is static and can be accessed / called directly through the class name

2, after calling the method() method in the main method, we can continue to invoke the method. We decide that method() has a return value.

3. After further observation, it is found that the show() method happens to be the method in the Inter2 interface, so the return value type is the Inter2 interface type

4. It is determined that the method() method has no parameters because the parameters calling the method() method are empty

The complete code is as follows:

interface Inter2{
    void show();
}

class Outer8{
    public static Inter2 method(){
//============Here is the code that needs to be supplemented==============
        return new Inter2() {
            @Override
            public void show() {
                System.out.println("HelloWorld");
            }
        };
    }
//============Here is the code that needs to be supplemented===============
}

public class InnerClassDemo9 {
    public static void main(String[] args) {
        Outer8.method().show();
    }
}

Common classes:

Relative path: take the project as the root directory (test.Test.src.com.changyonglei)

Absolute path / full path: with drive letter: (D:\IdeaProjects\src\test\Test\src\com\changyonglei\Student.java)

Object: explanation in API help document:

Class Object is the root of class Object structure.

Each class has Object as its superclass. All objects (including arrays) implement the methods of this class. Each class in java directly or indirectly inherits the Object class

Methods in Object class:

public int hashCode()

Returns the hash code value of the object.

This method is supported for hash tables, as provided by HashMap. Note: the hash code value here is a value calculated according to the hash algorithm. This value is related to the address, but the address value returned here is not the actual address value

Now it is simply understood as another form of address value.

public final Class getClass()

Returns the class of the Object. The Object returns the runtime class of the Object.

The returned class object is an object locked by the static synchronized method representing the class.

Examples of hashCode() and getclass() methods:

public class StduentTest {
    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println(s1.hashCode()); // 1163157884
        Student s2 = new Student();
        System.out.println(s2.hashCode()); // 1956725890
        Student s3 = s1;
        System.out.println(s3.hashCode()); // 1163157884
        System.out.println("=========================================");
        Student s4 = new Student();
        System.out.println(s4.getClass()); 
//    class test.Test.src.com.tys.day13.ketang.changyonglei.Student

        Class studentClass = s4.getClass();
//    Returns the name of the entity represented by the class object (class, interface, array class, primitive type or void) as a String.
        System.out.println(studentClass.getName());
//     test.Test.src.com.tys.day13.ketang.changyonglei.Student

        //Chain programming
        System.out.println(s4.getClass().getName());
 //    test.Test.src.com.tys.day13.ketang.changyonglei.Student


    }
}

Test results:

 public String toString()

Returns the string representation of the object.

Generally speaking, the toString method returns a string that "textually represents" the object. The result should be a concise expression that is easy to read. It is recommended that all subclasses override this method.

The toString class method Object returns an unsigned hexadecimal representation of the Object in which the Object is an instance, the string @ "of the class name of the symbolic character ` and the hash code of the Object.

In other words, this method returns a string equal to the following values:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Before rewriting, it is simply understood as: the relative path of the runtime class + the address value of the result of calling hsahCode

Integer: public static String toHexString(int i)

Returns the string representation of an integer parameter as an unsigned integer in 16 bits. Converts the hash value to an address value.

Although we know how to use the toString() method, the printed result is an address value that we can't understand. In other words, it's meaningless for us to get this result

Return the string representation of the object. In fact, we prefer to see the values of each member variable in the object.

It happens that toString() method is modified by public, and its return value is of String type, so we can override it in other classes

The rewritten toString() represents the value of each member variable in the print object

In the future, it can be generated automatically without handwriting under special circumstances.

Version 4.0 of a standard class:

Member variable: decorated with private keyword

Construction method: a parameterless. A method with all parameters.

Member method: setXxx(...)/getXxx()

toString(): it can be generated automatically instead of our previous show method.

Overridden toString method case

public class Student2 extends Object {
    private String name;
    private int age;

    public Student2() {
    }

    public Student2(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;
    }

//    @Override
//    public String toString() {
//
//
//========toString after rewriting========
    @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
//========toString after rewriting========
}

//Test class
public class StudentTest2 {
    public static void main(String[] args) {
        Student2 s = new Student2();
        System.out.println(s.toString());
        // test.Test.src.com.tys.day13.ketang.changyonglei.Student2@4554617c
        System.out.println("=======================================");
        System.out.println(s.getClass().getName());
        //test.Test.src.com.tys.day13.ketang.changyonglei.Student2
        System.out.println("=======================================");
        //toString() is equivalent to getclass() getName() + '@' + Integer. toHexString(hashCode())
        //getClass().getName() + '@' + Integer.toHexString(hashCode())
        //s.getClass().getName()+'@'+ Integer.toHexString(s.hashCode())
        //this.getClass().getName()+'@'+ Integer.toHexString(this.hashCode())
        System.out.println(s.toString());
        System.out.println(s.getClass().getName()+"@"+Integer.toHexString(s.hashCode()));

        System.out.println("========================================");
        Student2 s2 = new Student2("Xiao Wang", 18);
        System.out.println(s2.toString());

    }
}

Output results:

public boolean equals(Object obj)

Indicates whether some other objects are equal to this.

In the future, when we want to find out the implementation of a method and why the result is, look at the source code, place the mouse cursor on the method to be seen, and press ctrl + left mouse button to view the source code

By observing the source code, it is found that the underlying implementation of the equals method in the Object class is still==

public boolean equals(Object obj) { return (this == obj); }

And = = when comparing reference data types, the comparison is the address value. When the address values are different, the return is false

==:

Basic data type: the comparison is whether the two values are the same

When referencing a data type: the comparison is whether the address values of the two objects are the same

equals:

Only referenced data types can be compared

In actual development, the equals method is called to compare whether the values of member variables are the same

So we should rewrite it in subclasses. We don't need to do it ourselves. It can be generated automatically

Summary: the equals method before rewriting compares the address value, and the equals method after rewriting compares the member variable value

Rewritten equals method case:

import java.util.Objects;

public class Student3 extends Object {
    private String name;
    private int age;

    public Student3() {
    }

    public Student3(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;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

//    ========This is the overridden equals method========
    @Override
    public boolean equals(Object o) {
        //this -- s1
        //o -- s2
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student3 student3 = (Student3) o;
        return age == student3.age && Objects.equals(name, student3.name);
    }
//    ========This is the overridden equals method========
}

//Test class:
public class StudentTest3 {
    public static void main(String[] args) {
        Student3 s1 = new Student3("Xiao Liu", 18);
        Student3 s2 = new Student3("Xiao Liu", 18);
        System.out.println(s1==s2); // false
        Student3 s3 = s1;
        System.out.println(s1==s3); // true
        System.out.println("==========================");
        System.out.println(s1.equals(s2));  //true
        System.out.println(s1.equals(s3)); // true
        System.out.println(s1.equals(s1)); // true

        Student3 s4 = new Student3("Xiao Wang", 19);
        System.out.println(s1.equals(s4));//false
    }
}

Output results:

 

 

protected void finalize():

When the garbage collection determines that there is no longer a reference to the object, the garbage collector calls the object on the object. A subclass overrides the finalize method that handles system resources or performs other cleanup. Simply understand that this method is used for garbage collection, when to collect, uncertain GC mechanism, marking method.

protected Object clone()

Create and return a copy of this object. Perform specific cloning work.

If subclasses in other packages want to use the method modified by protected, use the super keyword to call.

clone's method Object performs specific cloning operations.

First, if the class of this object does not implement the interface clonable, CloneNotSupportedException is thrown.

If a class wants to use clone(), it must implement the clonable interface

By observing the API, it is found that there are no constants or abstract methods in the clonable interface. In the future, we will see an interface similar to clonable, which has nothing in it. We call it the tag interface.

There are two common types of copy in the IT industry:

Shallow copy: shallow copy means that the address value of the internal reference type variable of the copied object is the same as that of the original object (pointing to the same object), but the entire copied object and the new object are not the same address value.

Deep copy: copy all the contents of the copied object, including the reference type of memory. When copying, re create an object, and the value of the member variable is the same as that of the original copied object. However, subsequent modifications to the copied reference data type variables will not affect the original copied.

Copy case:

//Cop1 implements the tag interface clonable, which indicates that this is allowed to be cloned
class Cop1 extends Object implements Cloneable {
    private String name;
    private int age;
    private Demo demo;//Define reference data type variables

    public Cop1() {
    }

    public Cop1(String name, int age, Demo demo) {
        this.name = name;
        this.age = age;
        this.demo=demo;
    }

    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 Demo getDemo() {
        return demo;
    }

    public void setDemo(Demo demo) {
        this.demo = demo;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Cop1 cop1 = (Cop1) o;
        return age == cop1.age && name.equals(cop1.name) && demo.equals(cop1.demo);
    }


    @Override
    public String toString() {
        return "Cop1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", demo=" + demo +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

//Test class:
public class Test7Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Demo demo=new Demo();
        Cop1 c1=new Cop1("Xiao Hei",24,demo);
        Object c2 = c1.clone();//c1 clone object c2. Implies a polymorphism
        Cop1 c3=(Cop1)c1;//Downward transformation
        System.out.println(c1.toString());//Member variable value of the object before copying
        System.out.println(c3.toString());//Member variable value of the copied object
        System.out.println("=============================");
        System.out.println("c1 in demo Address value of object:"+c1.getDemo().hashCode());
        System.out.println("c2 in demo Address value of object:"+c3.getDemo().hashCode());
        //Compare the address value of the demo before copying with that after copying
        //It is found that the demo address value is the same
        System.out.println("=============================");
        System.out.println("c1 Address value of the overall object:"+c1.hashCode());
        System.out.println("c2 Address value of the overall object:"+c2.hashCode());
        //The address value of the whole object before copying and the address value of the whole object after copying
        //It is found that the address value after copying is different from that of the original object
        System.out.println("=============================");
    }
}

Output results:

By observing the output results, it is concluded that clone() is a shallow copy

Topics: Java C# linq p2p