Detailed use of some of the basic concepts in Java

  • 2020-04-01 01:51:15
  • OfStack

Class initialization order
In Java, classes may contain: static variables, static initializer blocks, member variables, initializer blocks, constructors. There may be inheritance relationships between classes, so when we instantiate an object, what is the loading order of the above parts?

First look at the code:


class Parent
 {
     public static StaticVarible staticVarible= new StaticVarible(" The parent class - A static variable 1");    
     public StaticVarible instVarible= new StaticVarible(" The parent class - Member variables 1");

     static
     {
         System.out.println(" The parent class - A static block ");
     }

     {
         System.out.println(" The parent class - The initialization block ");
     }

     public static StaticVarible staticVarible2= new StaticVarible(" The parent class - A static variable 2");    
     public StaticVarible instVarible2= new StaticVarible(" The parent class - Member variables 2");

     public Parent()
     {
         System.out.println(" The parent class - Instance constructor ");
     }
 }

 class Child extends Parent
 {
     public static StaticVarible staticVarible= new StaticVarible(" A subclass - A static variable 1");    
     public StaticVarible instVarible= new StaticVarible(" A subclass - Member variables 1");

     static
     {
         System.out.println(" A subclass - A static block ");
     }

     public Child()
     {
         System.out.println(" A subclass - Instance constructor ");
     }

     {
         System.out.println(" A subclass - The initialization block ");
     }

     public static StaticVarible staticVarible2= new StaticVarible(" A subclass - A static variable 2");    
     public StaticVarible instVarible2= new StaticVarible(" A subclass - Member variables 2");

     
 }

 class StaticVarible
 {
     public StaticVarible(String info)
     {
         System.out.println(info);
     }
 }

Then execute the following statement:

Child child = new Child();

The output results are as follows:

 The parent class - A static variable 1
 The parent class - A static block 
 The parent class - A static variable 2
 A subclass - A static variable 1
 A subclass - A static block 
 A subclass - A static variable 2
 The parent class - Member variables 1
 The parent class - The initialization block 
 The parent class - Member variables 2
 The parent class - Instance constructor 
 A subclass - Member variables 1
 A subclass - The initialization block 
 A subclass - Member variables 2
 A subclass - Instance constructor 

conclusion
From the above results, it can be seen that when instantiating an object, the loading order of each part is as follows:

Parent class static member/parent class static initialization block -> Subclass static member/subclass initialization block -> Parent class member variable/parent class initialization block -> Parent constructor -> Subclass member variable/subclass initialization block -> Subclass constructor

Something about String
First, let's talk about stacks and stacks in Java.

The & # 8226; Stack: store basic types, including the char/byte/short/int/long/float/double/Boolean
The & # 8226; Heap: holds a reference type and generally keeps a pointer to it in the stack. Garbage collection determines whether an object is recyclable by determining whether there is a pointer on the stack to an object in the heap.
As a special data type, String is not exactly the same as the basic type, nor is it the whole reference type, and it can be found in many interview questions.

Storage structure for variables of type String
The storage structure of String is divided into two parts, we start with String a = "ABC "; For example, describe the storage mode of String type:

1) create a char array on the stack with values of 'a', 'b', 'c'.

2) create a String object in the heap.

String pools in Java
To save space and resources, the JVM maintains a pool of strings, or caches a portion of the strings that were previously present.

For example, the following code:


String v1 = "ab";
String v2 = "ab";

In fact, v1==v2, because the JVM has already cached the "ab" after the v1 declaration.

So what is the basis for the JVM to cache strings? Let's look at the following code, which is very interesting:


public class StringTest {
     public static final String constValue = "ab";
     public static final String staticValue;

     static
     {
         staticValue="ab";
     }

     public static void main(String[] args)
     {
         String v1 = "ab";
         String v2 = "ab";
         System.out.println("v1 == v2 : " + (v1 == v2));
         String v3 = new String("ab");
         System.out.println("v1 == v3 : " + (v1 == v3));
         String v4 = "abcd";
         String v5 = "ab" + "cd";
         System.out.println("v4 == v5 : " + (v4 == v5));
         String v6 = v1 + "cd";
         System.out.println("v4 == v6 : " + (v4 == v6));
         String v7 = constValue + "cd";
         System.out.println("v4 == v7 : " + (v4 == v7));
         String v8 = staticValue + "cd";
         System.out.println("v4 == v8 : " + (v4 == v8));
         String v9 = v4.intern();
         System.out.println("v4 == v9 :" + (v4 == v9));
         String v10 = new String(new char[]{'a','b','c','d'});
         String v11 = v10.intern();
         System.out.println("v4 == v11 :" + (v4 == v11));
         System.out.println("v10 == v11 :" + (v10 == v11));
     }
 }

Note its output:

v1 == v2 : true
v1 == v3 : false
v4 == v5 : true
v4 == v6 : false
v4 == v7 : true
v4 == v8 : false
v4 == v9 :true
v4 == v11 :true
v10 == v11 :false

We will find that not all judgments return true, which seems to contradict the above statement. Not really, because

conclusion
1. The JVM can only cache constants that can be determined at compile time, not at run time.

ConstValue in the code above is a compile-time constant, while staticValue is a run-time constant.

2. The JVM caches strings differently by creating them in new.

So in this code, v1 is not the same as v3.

Is the design of String in the meta mode?
This is an interesting topic. Most articles on design patterns use String as an example when they talk about enjoying, but is it enjoying?

You can refer to the following article: (link: http://jb51.net/article/36864.htm) The inverted output of a string
In this case, it is common to think of a string as an array of characters and then reverse the string by reversing the array.

Fancy method calls
There are method calls in the inheritance relationship structure
Inheritance is a common method in object-oriented design, which effectively implements "code reuse", and subclasses have the freedom to override superclass methods, which can cause problems in calling superclass methods or subclass methods.

Look at the following code:


public class PropertyTest {

     public static void main(String[] args)
     {
         ParentDef v1 = new ParentDef();
         ParentDef v2 = new ChildDef();
         ChildDef v3 = new ChildDef();
         System.out.println("=====v1=====");
         System.out.println("staticValue:" + v1.staticValue);
         System.out.println("value:" + v1.value);
         System.out.println("=====v2=====");
         System.out.println("staticValue:" + v2.staticValue);
         System.out.println("value:" + v2.value);
         System.out.println("=====v3=====");
         System.out.println("staticValue:" + v3.staticValue);
         System.out.println("value:" + v3.value);
     }
 }

 class ParentDef
 {
     public static final String staticValue = " Parent class static variables ";
     public String value = " Parent instance variable ";
 }

 class ChildDef extends ParentDef
 {
     public static final String staticValue = " Subclass static variable ";
     public String value = " Subclass instance variable ";
 }

The output results are as follows:

=====v1=====
staticValue: Parent class static variables 
value: Parent instance variable 
=====v2=====
staticValue: Parent class static variables 
value: Parent instance variable 
=====v3=====
staticValue: Subclass static variable 
value: Subclass instance variable 

conclusion
Whether a superclass method is called or a subclass method is related only to the declared type of the variable, not to the instantiated type.

Is it a value pass or a reference pass
My point on this topic is value passing, because all that is passed is what is stored on the stack, whether it is a value of a primitive type or a pointer to an object in the heap, which is a value rather than a reference. And as the value is passed, the JVM copies the value and passes the copied value to the calling method.

In this way, let's look at the following code:


public class ParamTest {

     public void change(int value)
     {
         value = 10;
     }

     public void change(Value value)
     {
         Value temp = new Value();
         temp.value = 10;
         value = temp;
     }

     public void add(int value)
     {
         value += 10;
     }

     public void add(Value value)
     {
         value.value += 10;
     }

     public static void main(String[] args)
     {
         ParamTest test = new ParamTest();
         Value value = new Value();
         int v = 0;
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
         System.out.println("=====change=====");
         test.change(v);
         test.change(value);
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
         value = new Value();
         v = 0;
         System.out.println("=====add=====");
         test.add(v);
         test.add(value);
         System.out.println("v:" + v);
         System.out.println("value.value:" + value.value);
     }
 }

 class Value
 {
     public int value;
 }

Its output result:

v:0
value.value:0
=====change=====
v:0
value.value:0
=====add=====
v:0
value.value:10

We see that change the call method, even if we pass in is a pointer to the object, but in the end object's properties and no change, this is because the body change method, we built an object, and then "copy of the pointer to the original object" points to the "new object", and is adjusted to the new attributes of the object. But the "pointer to the original object before the copy" is still pointing to the "original object", and there is no property change.

The difference between final/finally/finalize
Final can modify classes, member variables, methods, and method parameters. Classes with final modification cannot be inherited, methods with final modification cannot be overridden, and variables with final modification can only be assigned once.

The assignment time of using the final declaration variable:

1) assignment when defining declarations

2) initialization block or static initialization block

3) constructor

Look at the following code:


class FinalTest
 {
     public static final String staticValue1 = " A static variable 1";
     public static final String staticValue2;

     static
     {
         staticValue2 = " A static variable 2";
     }

     public final String value1 = " The instance variables 1";
     public final String value2;
     public final String value3;

     {
         value2 = " The instance variables 2";
     }

     public FinalTest()
     {
         value3 = " The instance variables 3";
     }
 }

Finally generally means and try... Catch is used together to free up resources.

Let's look at the following code:


public class FinallyTest {

     public static void main(String[] args)
     {
         finallyTest1();
         finallyTest2();
         finallyTest3();
     }

     private static String finallyTest1()
     {
         try
         {
             throw new RuntimeException();
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
         finally
         {
             System.out.println("Finally Statement executed ");
         }
         try
         {
             System.out.println("Hello World");
             return "Hello World";
         }
         catch(Exception ex)
         {
             ex.printStackTrace();
         }
         finally
         {
             System.out.println("Finally Statement executed ");
         }
         return null;
     }

     private static void finallyTest2()
     {
         int i = 0;
         for (i = 0; i < 3; i++)
         {
             try
             {
                 if (i == 2) break;
                 System.out.println(i);
             }
             finally
             {
                 System.out.println("Finally Statement executed ");
             }
         }
     }

     private static Test finallyTest3()
     {
         try
         {
             return new Test();
         }
         finally
         {
             System.out.println("Finally Statement executed ");
         }
     }
 }

The implementation results are as follows:

java.lang.RuntimeException
    at sample.interview.FinallyTest.finallyTest1(FinallyTest.java:16)
    at sample.interview.FinallyTest.main(FinallyTest.java:7)
Finally Statement executed 
Hello World
Finally Statement executed 
Finally Statement executed 
Finally Statement executed 
Finally Statement executed 
Test Instances are created 
Finally Statement executed 

Notice that during the loop, for one loop, finally executes even if break or continue is called.

Finalize is primarily used to free up resources, which is called when a GC method is called.

Consider the following example:


class FinalizeTest
 {
     protected void finalize()
     {
         System.out.println("finalize Method is called ");
     }

     public static void main(String[] args)
     {
         FinalizeTest test = new FinalizeTest();
         test = null;
         Runtime.getRuntime().gc();
     }
 }

The implementation results are as follows:

finalize Method is called 

Something about basic types
For is divided into nine kinds of basic types, including byte/short/int/long/float/double/Boolean/void, each basic type corresponds to a "packaging", some other basic information is as follows:

.  Basic type: byte  Binary digits: 8
.  Packing: java.lang.Byte
.  The minimum: Byte.MIN_VALUE=-128
.  Max: Byte.MAX_VALUE=127
.  Basic type: short  Binary digits: 16
.  Packing: java.lang.Short
.  The minimum: Short.MIN_VALUE=-32768
.  Max: Short.MAX_VALUE=32767
.  Basic type: int  Binary digits: 32
.  Packing: java.lang.Integer
.  The minimum: Integer.MIN_VALUE=-2147483648
.  Max: Integer.MAX_VALUE=2147483647
.  Basic type: long  Binary digits: 64
.  Packing: java.lang.Long
.  The minimum: Long.MIN_VALUE=-9223372036854775808
.  Max: Long.MAX_VALUE=9223372036854775807
.  Basic type: float  Binary digits: 32
.  Packing: java.lang.Float
.  The minimum: Float.MIN_VALUE=1.4E-45
.  Max: Float.MAX_VALUE=3.4028235E38
.  Basic type: double  Binary digits: 64
.  Packing: java.lang.Double
.  The minimum: Double.MIN_VALUE=4.9E-324
.  Max: Double.MAX_VALUE=1.7976931348623157E308
.  Basic type: char  Binary digits: 16
.  Packing: java.lang.Character
.  The minimum: Character.MIN_VALUE=0
.  Max: Character.MAX_VALUE=65535

Some conclusions about basic types (from the Java interview puzzle)
The & # 8226; Integers without character suffixes are of type int by default; Floating point Numbers without character suffixes are of type double by default.
The & # 8226; If the value of an integer is beyond the range that an int can represent, the suffix "L" must be appended (case-insensitive, uppercase is recommended because lowercase L is easily confused with the Arabic numeral 1), denoted as long.
The & # 8226; Integers and floating-point Numbers with an "F" (case-insensitive) suffix are of type float; Integers and floating point Numbers with a "D" (case-insensitive) suffix are of type double.
The & # 8226; The compiler checks the values of byte, short, int, long, float, double, and char variables at compile time and reports an error if they exceed their range.
The & # 8226; Int values can be assigned to variables of all numeric types; Long values can be assigned to variables of type long, float, or double; Float values can be assigned to variables of float or double; A double value can only be assigned to a double variable.
About conversions between basic types
The following conversion is the conversion of lossless accuracy:

The & # 8226; Byte - > short
The & # 8226; Short - > int
The & # 8226; Char - > int
The & # 8226; Int - > long
The & # 8226; Float - > A double
The following conversion will lose precision:

The & # 8226; Int - > float
The & # 8226; Long - > float
The & # 8226; Long - > A double
Any other conversion is illegal.

Something about the date
In Java, there are two classes related to dates, one is Date and one is Calendar. Let's look at the following example:


public class DateTest {

     public static void main(String[] args) throws ParseException
     {
         test1();
         test2();
         test3();
     }

     private static void test1() throws ParseException
     {
         Date date = new Date();
         System.out.println(date);
         DateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
         System.out.println(sf.format(date));
         String formatString = "2013-05-12";
         System.out.println(sf.parse(formatString));
     }

     private static void test2()
     {
         Date date = new Date();
         System.out.println("Year:" + date.getYear());
         System.out.println("Month:" + date.getMonth());
         System.out.println("Day:" + date.getDate());
         System.out.println("Hour:" + date.getHours());
         System.out.println("Minute:" + date.getMinutes());
         System.out.println("Second:" + date.getSeconds());
         System.out.println("DayOfWeek:" + date.getDay());
     }

     private static void test3()
     {
         Calendar c = Calendar.getInstance();
         System.out.println(c.getTime());
         System.out.println(c.getTimeZone());
         System.out.println("Year:" + c.get(Calendar.YEAR));
         System.out.println("Month:" + c.get(Calendar.MONTH));
         System.out.println("Day:" + c.get(Calendar.DATE));
         System.out.println("Hour:" + c.get(Calendar.HOUR));
         System.out.println("HourOfDay:" + c.get(Calendar.HOUR_OF_DAY));
         System.out.println("Minute:" + c.get(Calendar.MINUTE));
         System.out.println("Second:" + c.get(Calendar.SECOND));
         System.out.println("DayOfWeek:" + c.get(Calendar.DAY_OF_WEEK));
         System.out.println("DayOfMonth:" + c.get(Calendar.DAY_OF_MONTH));
         System.out.println("DayOfYear:" + c.get(Calendar.DAY_OF_YEAR));
     }
 }

The output results are as follows:

Sat May 11 13:44:34 CST 2013
-05-11
Sun May 12 00:00:00 CST 2013
Year:113
Month:4
Day:11
Hour:13
Minute:44
Second:35
DayOfWeek:6
Sat May 11 13:44:35 CST 2013
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
Year:2013
Month:4
Day:11
Hour:1
HourOfDay:13
Minute:44
Second:35
DayOfWeek:7
DayOfMonth:11
DayOfYear:131

It is important to note that the getxxx method in Date has become deprecated, so we try to use the calendar.get method to get the details of the Date.
Also, note DateFormat, which not only formats the output of a date, but also reverts to convert a format-compliant string to a date type.


Related articles: