IV. Java API s in Common Use

IV. Java API s in Common Use

Can switch work on byte, on long and on String?

Before Java 5 switch(expr), expr could only be byte, short, char, int. Since Java 5, enumeration types have been introduced into Java, and expr can also be enum types. Starting with Java 7, expr can also be String, but long integers are not available in all current versions.

Please state the output of the following program

class StringEqualTest {
    public static void main(String[] args) {
        String s1 = "Programming";
        String s2 = new String("Programming");
        String s3 = "Program";
        String s4 = "ming";
        String s5 = "Program" + "ming";
        String s6 = s3 + s4;
        System.out.println(s1 == s2); //false
        System.out.println(s1 == s5); //true
        System.out.println(s1 == s6); //false
        System.out.println(s1 == s6.intern()); //true
        System.out.println(s2 == s2.intern()); //false
    }
}

Plus: To answer the above questions, you need to know the following two knowledge points:

  1. The intern () method of the String object gets a reference to the corresponding version of the string object in the constant pool (if there is a string in the constant pool and the equals result of the String object is true), if there is no corresponding string in the constant pool, the string will be added to the constant pool and returned to the constant pool. References to strings;

  2. The'+'operation of strings essentially creates StringBuilder objects for append operations, and then processes stitched StringBuilder objects into String objects by toString method. This can be seen from the JVM bytecode instructions corresponding to class files obtained by javap-c StringEqualTest. class command. .

Under what circumstances is string connection using the "+" operator better than using the append method of the StringBuffer/StringBuilder object to connect strings?

The topic comes from Huawei.
Strings are one of the most commonly used data structures in Java programs. String classes have been overloaded with "+" in Java. In other words, strings can be direct
Use "+" to connect, as shown in the following code:

String s = "abc" + "ddd";

But is that really good? Of course, this question cannot be answered simply by yes or no. It should be decided according to the specific circumstances. A StringBuilder class is provided in Java (this class is only available in J2SE5 and above, and previous versions use the StringBuffer class), which can also play a "+" role. So which one should we use?

Let's first look at the following code:

public class TestSimplePlus {
    public static void main(String[] args){
        String s = "abc";   
        String ss = "ok" + s + "xyz" + 5;
        System.out.println(ss);
    }
}

The above code will output the correct result. On the surface, there's no difference between using "+" for strings and integers, but is that really the case? Let's take a look at the nature of this code. We first decompile TestSimplePlus into Java Byte Code using decompilation tools (such as javap or jad with jdk), and the mystery is clear at a glance. In this article, jad will be used to decompile, with the following commands:
jad -o -a -s d.java TestSimplePlus.class

The decompiled code is as follows:

package com.starkfang.test;

import java.io.PrintStream;

public class TestSimplePlus
{

    public TestSimplePlus()
    {
    //    0    0:aload_0         
    //    1    1:invokespecial   #1   <Method void Object()>
    //    2    4:return          
    }

    public static void main(String args[])
    {
        String s = "abc";
    //    0    0:ldc1            #2   <String "abc">
    //    1    2:astore_1        
        String s1 = (new StringBuilder()).append("ok").append(s).append("xyz").append(5).toString();
    //    2    3:new             #3   <Class StringBuilder>
    //    3    6:dup             
    //    4    7:invokespecial   #4   <Method void StringBuilder()>
    //    5   10:ldc1            #5   <String "ok">
    //    6   12:invokevirtual   #6   <Method StringBuilder StringBuilder.append(String)>
    //    7   15:aload_1         
    //    8   16:invokevirtual   #6   <Method StringBuilder StringBuilder.append(String)>
    //    9   19:ldc1            #7   <String "xyz">
    //   10   21:invokevirtual   #6   <Method StringBuilder StringBuilder.append(String)>
    //   11   24:iconst_5        
    //   12   25:invokevirtual   #8   <Method StringBuilder StringBuilder.append(int)>
    //   13   28:invokevirtual   #9   <Method String StringBuilder.toString()>
    //   14   31:astore_2        
        System.out.println(s1);
    //   15   32:getstatic       #10  <Field PrintStream System.out>
    //   16   35:aload_2         
    //   17   36:invokevirtual   #11  <Method void PrintStream.println(String)>
    //   18   39:return          
    }
}

One of the benefits of using jad decompilation here is that bytecode and source code can be generated simultaneously. This can be a comparative study. It's easy to see from the above code
Out, although "+" is used in the source program, it is still converted to StringBuilder at compile time. So we can conclude that in Java
String Builder is actually used regardless of the way string connections are performed.
So can we deduce from this conclusion that using "+" and StringBuilder works the same way? This should be explained in two ways. If
Explaining from the running results, then "+" and StringBuilder are completely equivalent. But in terms of operational efficiency and resource consumption, they will exist very well.
Big difference.
Of course, if the serial expression of the connection character is simple (such as the sequence structure above), then "+" is basically the same as StringBuilder, but if
The structure is more complex, such as the use of loops to connect strings, the resulting Java Byte Code will be very different. First let's look at the following generation
Code:

public class TestComplexPlus {
    public static void main(String[] args) {
        String s = "";
        Random rand = new Random();
        for (int i = 0; i < 10; i++) {
            s = s + rand.nextInt(1000) + " ";
        }
        System.out.println(s);
    }
}

The Java Byte Code after recompilation of the above code is as follows:

package com.starkfang.test;

import java.io.PrintStream;
import java.util.Random;

public class TestComplexPlus
{

    public TestComplexPlus()
    {
    //    0    0:aload_0         
    //    1    1:invokespecial   #1   <Method void Object()>
    //    2    4:return          
    }

    public static void main(String args[])
    {
        String s = "";
    //    0    0:ldc1            #2   <String "">
    //    1    2:astore_1        
        Random random = new Random();
    //    2    3:new             #3   <Class Random>
    //    3    6:dup             
    //    4    7:invokespecial   #4   <Method void Random()>
    //    5   10:astore_2        
        for(int i = 0; i < 10; i++)
    //*   6   11:iconst_0        
    //*   7   12:istore_3        
    //*   8   13:iload_3         
    //*   9   14:bipush          10
    //*  10   16:icmpge          55
            s = (new StringBuilder()).append(s).append(random.nextInt(1000)).append(" ").toString();
    //   11   19:new             #5   <Class StringBuilder>
    //   12   22:dup             
    //   13   23:invokespecial   #6   <Method void StringBuilder()>
    //   14   26:aload_1         
    //   15   27:invokevirtual   #7   <Method StringBuilder StringBuilder.append(String)>
    //   16   30:aload_2         
    //   17   31:sipush          1000
    //   18   34:invokevirtual   #8   <Method int Random.nextInt(int)>
    //   19   37:invokevirtual   #9   <Method StringBuilder StringBuilder.append(int)>
    //   20   40:ldc1            #10  <String " ">
    //   21   42:invokevirtual   #7   <Method StringBuilder StringBuilder.append(String)>
    //   22   45:invokevirtual   #11  <Method String StringBuilder.toString()>
    //   23   48:astore_1        

    //   24   49:iinc            3  1
    //*  25   52:goto            13
        System.out.println(s);
    //   26   55:getstatic       #12  <Field PrintStream System.out>
    //   27   58:aload_1         
    //   28   59:invokevirtual   #13  <Method void PrintStream.println(String)>
    //   29   62:return          
    }
}

As you can see, although the compiler converts "+" into StringBuilder, the location where StringBuilder objects are created is inside the for statement. This means that every time a loop is executed, a StringBuilder object (in this case, 10 StringBuilder objects) is created, and although Java has a garbage collector, the working time of the collector is variable. If such garbage is produced continuously, it will still occupy a lot of resources. The solution to this problem is to use StringBuilder to connect strings directly in the program. The code is as follows:

 public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        Random rand = new Random();
        for (int i = 0; i < 10; i++) {
            sb.append(rand.nextInt(1000));
            sb.append(" ");
        }
        System.out.println(sb.toString());
    }

The code to create StringBuilder is placed outside the for statement. Although this processing looks like it's in the source program
It's complex, but it's more efficient and consumes less resources.

When using StringBuilder, be careful not to mix "+" with StringBuilder, otherwise more StringBuilder objects will be created, as follows:

for (int i = 0; i < 10; i++){
    result.append(rand.nextInt(1000));
    result.append(" ");
}

Change to the following form:

for (int i = 0; i < 10; i++){
    result.append(rand.nextInt(1000) + " ");
}

The decompiled results are as follows:

for(int i = 0; i < 10; i++)
    //* 10 19:iconst_0
    //* 11 20:istore 4
    //* 12 22:goto 65
    {
    result.append((new StringBuilder(String.valueOf(rand.nextInt(1000)))).append(" ").toString());
    // 13 25:aload_3
    // 14 26:new #21 <Class StringBuilder>
    // 15 29:dup

As can be seen from the above code, the Java compiler compiles "+" into StringBuilder, so that a StringBuilder object is created every time the for statement is looped. If the above code is compiled under JDK 1.4, StringBuilder must be changed to StringBuffer, while JDK 1.4 converts "+" to StringBuffer (because JDK 1.4 converts"+"to StringBuffer). JDK 1.4 does not provide StringBuilder classes. StringBuffer and StringBuilder are basically the same, except that StringBuffer is thread-safe, while StringBuilder is not thread-safe. Therefore, StringBuilder is more efficient.

  • Reference on "Why Alibaba does not recommend using"+"for string splicing in for loops" here.

Date and time in java 8

public static void main(String[] args) {
    //Get the year, month, day, hour, minute, second
    LocalDateTime dt = LocalDateTime.now();
    System.out.println(dt.getYear());
    System.out.println(dt.getMonthValue()); // 1 - 12
    System.out.println(dt.getDayOfMonth());
    System.out.println(dt.getHour());
    System.out.println(dt.getMinute());
    System.out.println(dt.getSecond());

    //Get the number of milliseconds from 0:0:0 on January 1, 1970 to the present
    Clock.systemDefaultZone().millis();

    //Get the last day of a month
    LocalDate today = LocalDate.now();
    LocalDate firstday = LocalDate.of(today.getYear(),today.getMonth(),1);
    LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());
    System.out.println("The first day of the month"+firstday);
    System.out.println("Last day of the month"+lastDay);

    //format date
    DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    LocalDate date2 = LocalDate.now();
    System.out.println(date2.format(newFormatter));

    //Achieve the present moment of yesterday
    LocalDateTime today = LocalDateTime.now();
    LocalDateTime yesterday = today.minusDays(1);
    System.out.println(yesterday);

     //Current timestamp
     Instant timestamp = Instant.now();
     System.out.println("Current timestamp = "+timestamp.toEpochMilli());
     Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli());
     System.out.println("Turn to Instant = "+specificTime);
}

New time and date API s are introduced in Java 8, including LocalDate, LocalTime, LocalDateTime, Clock, Instant and other classes, which are designed with invariant patterns.
This is a thread-safe design.

Keywords: Java JDK Programming jvm

Added by Peter on Mon, 26 Aug 2019 12:29:56 +0300