JDK 11学习

Module 模块的使用

  1. Exports packages,Requires modules

Remember that “packages are exported” and “modules are required”. A module exports packages to other modules. It cannot export individual classes.

On the other hand, a module cannot specify a particular package or a class in the requires clause. It can only specify the name of the module in which the required package exists.

  1. 星号 * 不允许存在在requires 或者 exports语句中

There cannot be any * in exports or requires clause.

*错误使用方法`

  module acme.db {  
     exports com.acme.*;
      } 
  1. CMD to run Module

–module implies that you want to run a module. But to run a module, you need to specify the location where the module can be found using the --module-path option.
-classpath option is used when you want to run a class directly.
For example, java -classpath foobar.jar com.foo.Bar (Observe that unlike module-path, classpath uses a single dash)

You need to know about three command line options for running a class that is contained in a module:
3.1. --module-path or -p: This option specifies the location(s) of the module(s) that are required for execution. This option is very versatile. You can specify exploded module directories, directories containing modular jars, or even specific modular or non-modular jars here. The path can be absolute or relative to the current directory. For example, --module-path c:/javatest/output/mathutils.jar or --module-path mathutils.jar You can also specify the location where the module’s files are located. For example, if your module is named abc.math.utils and this module is stored in c:\javatest\output, then you can use: --module-path c:/javatest/output. Remember that c:\javatest\output directory must contain abc.math.utils directory and the module files (including module-info.class) must be present in their appropriate directory structure under abc.math.utils directory. You can specify as many jar files or module locations separated by path separator (; on windows and : on *nix) as required. NOTE: -p is the short form for --module-path.(Observe the single and double dashes).
3.2. --module or -m: This option specifies the module that you want to run. For example, if you want to run abc.utils.Main class of abc.math.utils module, you should write --module abc.math.utils/abc.utils.Main If a module jar specifies the Main-Class property its MANIFEST.MF file, you can omit the main class name from --module option. For example, you can write, --module abc.math.utils instead of --module abc.math.utils/abc.utils.Main. NOTE: -m is the short form for --module.(Observe the single and double dashes). Thus, java --module-path mathutils.jar --module abc.math.utils/abc.utils.Main is same as java -p mathutils.jar -m abc.math.utils/abc.utils.Main NOTE: It is possible to treat modular code as non-modular by ignoring module options altogether. For example, if you want to run the same class using the older classpath option, you can do it like this: java -classpath mathutils.jar abc.utils.Main
3.3. -classpath: Remember that modular code cannot access code present on the -classpath but “automatic modules” are an exception to this rule. When a non-modular jar is put on --module-path, it becomes an “automatic module” but it can still access all the modular as well as non-modular code. In other words, a class from an automatic module can access classes present on --module-path as well as on -classpath without having any “requires” clause (remember that there is no module-info in automatic modules). Thus, if your modular jar A depends on a non-modular jar B, you have to put that non-modular jar B on --module-path. You must also add appropriate requires clause in your module A’s module-info otherwise compilation of your module will not succeed. Further, if the non-modular jar B depends on another non-modular jar C, then the non-modular jar C may be put on the classpath or module-path.

-classpath is used only when you want to make non-modular classes accessible to other non modular classes.

Lambda的用法

  1. 从lambda表达式引用的局部变量必须是final,否则会有编译错误

Java编译器实现的只是capture-by-value,并没有实现capture-by-reference。
匿名内部类来自外部闭包环境的自由变量必须是final的。

Interface 接口

  1. A default method must have a body.
  2. An interface can have a static method but the method must have a body.
  3. static methods can never be abstract (neither in an interface nor in a class).
  4. An interface can redeclare a default method and provide a different implementation.
  5. An interface can redeclare a default method and also make it abstract.
  6. Trying to override a static method with a non-static method (and vice-versa) in a class will result in a compilation error. Even in case of interfaces, a subinterface cannot override a default method with a static method.
    You can, however, have a default method in a subinterface with the same signature as a static method of its super interface because a static method of an interface can only be called using that interface’s name.

Here are some points to remember:
A class is uninstantiable if the class is declared abstract. If a method has been declared as abstract, it cannot provide an implementation (i.e. it cannot have a method body ) and the class containing that method must be declared abstract).
If a method is not declared abstract, it must provide a method body (the class can be abstract but not necessarily so).
If any method in a class is declared abstract, then the whole class must be declared abstract. An class can still be made abstract even if it has no abstract method.

接口中属性,无论是否指定这些关键字(Public , static, final ),接口中的任何字段都是public,static 和final的。
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)

Example:

interface I{    
   public default void invalid(){ }   
   public static void valid(){ } //Can be called only using I.valid(); 
 }  
interface I2 extends I{  
   public static void invalid(){ } //WILL NOT COMPILE   
   public default void valid(){ } //this is ok.
     }
  1. Abstract Through Interface
    7.1 All fields of an interface are always final and static, even if you don’t specify the static or final keywords. However, they cannot be left uninitialized. They must be given a value explicitly.
    7.2. Java 9 onwards, an interface is allowed to have private methods (but not protected). Fields are always static and public.
    Only methods of an interface can be private. private/protected fields are not allowed.
interface Account{  
 public default String getId(){   
    return "0000";  
     } 
     }  
     interface PremiumAccount extends Account{  
       //INSERT CODE HERE    
       }

//code insert (1)
String getId();  // An interface can redeclare a default method and also make it abstract.

//or code insert (2)
default String getId(){    
return "1111"; 
}            //An interface can redeclare a default method and provide a different implementation.

FunctionInterface Example

public class Book{     
private int id;     
private String title; //constructors and accessors not shown } 

Insert Code

//Assuming that *book* is a reference to a valid Book object
Consumer c = b->System.out.println(b.getId()+":"+b.getTitle()); c.accept(book);

Remember that Consumer doesn’t return anything. Therefore, the body of the lambda expression used to capture Consumer must be an expression of type void.

继承 extends

Definition of Multiple inheritance

Multiple inheritance of state includes ability to inherit instance fields from multiple classes.
Multiple inheritance of type includes ability to implement multiple interfaces and/or ability to extend from multiple clases.
Java allows a class to implement multiple interfaces. An interface is a “type” and does not contain any state. This implies that Java supports multiple type inheritance.
A class contains state and extending a class means inheriting the state. Since Java does not allow a class to extend from multiple classes, it means that Java does not support multiple state inheritance.

Java supports multiple type inheritance. Java does not support multiple state inheritance.

Interfaces, classes, and enums are all “types”. Java allows a class to implement multiple interfaces. In this way, Java supports multiple inheritance of types.

“State”, on the other hand, is represented by instance fields. Only a class can have instance fields and therefore, only a class can have a state. (Fields defined in an interface are always implicitly static, even if you don’t specify the keyword static explicitly. Therefore, an interface does not have any state.) Since a class is allowed to extend only from one class at the most, it can inherit only one state. Thus, Java does not support multiple inheritance of state.

superclass reference cannot be assigned to subclass reference without explicit cast.

Example

 class A{    
 public int i = 10;    
 private int j = 20;  
 }  
 
 class B extends A{    
 private int i = 30; //1    
 public int k = 40; 
  } 
  
 class C extends B{ }  
 
 public class TestClass{    
 public static void main(String args[]){       
 C c = new C();       
 System.out.println(c.i); //2       
 System.out.println(c.j); //3       
 System.out.println(c.k);   
  } 
  } 
  //The code will print 40 if //2 and //3 are commented out.

Explanation

You cannot access c.i because i is private in B. But you can access ( (A)c).i because i is public in A. Remember that member variables are hidden and not overridden. So, B’s i hides A’s i and since B’s i is private, you can’t access A’s i unless you cast the reference to A. You cannot access c.j because j is private in A.

Example

 class A{    
     public int i = 10;    
     public int j = 20;  
     
 }  
 
 class B extends A{    
     public int i = 30; //1    
    public int k = 40;  
     private int j = 50; 
 }  
 
 class C extends B
 { }  
 
 public class Main{    
     public static void main(String args[]){       
         C c = new C();       
         System.out.println(c.i); //2       
         System.out.println(((A)c).j); //3       没有cast to A, 就会报错
         System.out.println(c.k);    
         
     } } 
// it will print   
 30
 20
 40

Example

 class A{    
     public int i = 10;    
     public int j = 20;  
     
 }  
 
 class B extends A{    
     public int i = 30; //1    
    public int k = 40;  
    
 }  
 
 class C extends B
 { }  
 
 public class Main{    
     public static void main(String args[]){       
         C c = new C();       
         System.out.println(c.i); //2       
         System.out.println(c.j); //3       
         System.out.println(c.k);    
         
     } } 
     //it  will print 
     30
     20
     40

Example

 class A{    
     public int i = 10;    
     public int j = 20;  
     
 }  
 
 class B extends A{    
     public int i = 30; //1    
    public int k = 40;  
    
 }  
 
 class C extends B
 { }  
 
 public class Main{    
     public static void main(String args[]){       
         C c = new C();       
         System.out.println(((A)c).i); //2       
         System.out.println(c.j); //3       
         System.out.println(c.k);    
         
     } } 
     //It will print
     10
     20
     40

instance variable is hidden and method is override during extends
在继承期间,实例变量被隐藏,方法被覆盖
Example

      class A{    
     public int i = 10;    
     private int j = 20;  
     public void hi(){
         System.out.println("hi A");
     }
      public void ha(){
         System.out.println("ha A"); //
     }
 }  
 
 class B extends A{    
     public int i = 30; //1    
    public int k = 40;  
    public int j=50;
       
    public void hi(){
         System.out.println("hi B");
     }
 }  
 
 class C extends B
 { 
 public int k = 60;
      public void hi(){
         System.out.println("hi C");//
     }
           
 }  
 
 public class Main{    
     public static void main(String args[]){       
         C c = new C();       
         System.out.println(c.i); //2       
         System.out.println(c.j); //3       
        System.out.println(c.k);  
         c.hi();
         //c.ha();
         ((A)c).ha();
         
     } }
     //it will print
     30
     50
     60
     hi C
     ha A

Overload重载

Overriding覆盖,重写

  1. An overriding method is not allowed to decrease accessibility.
    Accessibility(Public>Protected>default>private)
    Example
abstract class A{    
protected int m1(){ 
return 0; 
} } 
class B extends A{    
@Override    
int m1(){ 
return 1; 
} } 

Method m1() in super class A is more accessible than the overriding method in subclass B. An overriding method is not allowed to decrease accessibility.

  1. The concept here is that an overriding method cannot make the overridden method more private.
    The access hierarchy in increasing levels of accessibility is:
    private->‘no modifier’->protected->public ( public is accessible to all and private is accessible to none except itself.)
  1. protected’ means the method will be accessible to all the classes in the same package and all the subclasses (even if the subclass is in a different package).
    No modifier (which is the default level) means the method will be accessible only to all the classes in the same package. (i.e. not even to the subclass if the subclass is in a different package.)

重写override

To override a method in the subclass, the overriding method (i.e. the one in the subclass) MUST HAVE:

  1. same name
  2. same return type in case of primitives (a subclass is allowed for classes, this is also known as covariant return types). 相同的返回类型
    3 .same type and order of parameters .相同的参数类型和参数顺序
  3. it may throw only those exceptions that are declared in the throws clause of the superclass’s method or exceptions that are subclasses of the declared exceptions. 当且仅当父类方法抛出异常时,子类的重写方法才可以抛出 相同或者 父类抛出异常的子异常。
  4. It may also choose NOT to throw any exception.( The names of the parameter types do not matter.
    For example, void methodX(int i) is same as void methodX(int k)

**Since the original (overridden) method does not have any throws clause, the overriding method cannot declare any checked exceptions.(父类方法没有声明抛出异常,则子类不可以声明抛出checked exception,但是可以选择不抛出异常或者抛出unchecked exception)

According to the rule of covariant returns, an overriding method must return either the same type or a sub type of the type returned by the overridden method.

Steps to check for valid override

First, check the method signature (i.e. method name and the parameter list). If the signature of the method in the subclass matches the signature of the method in the super class, then it could be a valid override, otherwise it is just an overloaded method. Note that signature does not include parameter names and parameter’s generic type specification.

检查方法签名(方法名和参数列表)

Second, if it is a potential override, check the generic type specification of the parameters. If the overriding method does not use a generic type specification for the parameter type, then it is valid. The reverse is not valid i.e. the overriding method is allowed to erase the generic type specification but is not allowed to add a generic type specification if the overridden method does not have it. If both the methods have a generic type specification, then the specification must match exactly. For example, if the overridden method has Set<Integer>, then the overriding method can use Set or Set<Integer>. But if overridden method has Set, then the overriding method must also have Set for a valid override.

继承的子类形参允许删除泛型类型规范,但如果被覆盖的方法没有泛型类型规范,则不允许添加该泛型类型规范

Third, if it is a potential override, check the return type. Java allows “covariant” returns, which means, the return type of the overriding method must be the same or be a subtype of the return type mentioned in the overridden method. Check the two return types without the generic type specification. If return type of the overriding method is covariant with respect to the return type of the overriding method (for example, ArrayList is covariant with List), then perform the same check including the generic type specification (for example, ArrayList is covariant with List).

潜在覆盖,检查返回类型

Don’t get confused by the presence of <T> in the code. The same rules of overriding still apply. The T in <T> is called as the “type” parameter. It is used as a place holder for whatever type is actually used while invoking the method. For example, if you call the method <T> List<T> transform(List<T> list) with List<String>, T will be typed to String. Thus, it will return List<String>. If, in another place, you call the same method with Integer, T will be typed to Integer and therefore, the return type of the method for that invocation will be List<Integer>

Type erasure of generic method parameters

Remember that unlike arrays, generic collections are not reified, which means that all generic information is removed from the compiled class.
Thus, Set<CharSequence> and Set<String> are converted to just Set by the compiler while generating the class file. This implies that two methods whose parameter types differ only on the type specification are not really different methods.

For example, void m(Set<CharSequence> cs), void m(Set<String> s), and void m(Set<SomeOtherClass> o) are not different method signatures at all. If you remove the type specification, they all resolve to the same signature i.e. void m(Set x).

Hence, if you put them in the same class, the resulting class file will have two methods with the exact same signature. This is obviously a problem and so, the compiler rejects the code.If you put one of them in a superclass and another in a subclass, then from the compiler’s perspective they constitute valid overloading, however, from the JVM’s perspective it is an override and the JVM will not respect the compile time method binding done by the compiler based on the generic type specification. That is why Java does not allow this either.

The exception to this rule is that the overriding method is allowed to erase the generic type specification. For example, if the overridden method has Set<Integer>, then the overriding method can use Set or Set<Integer>. But if overridden method has Set, then the overriding method must also have Set for a valid override.

Rule of Covariant Returns协变返回规则

An overriding method (i.e. a sub class’s method) is allowed to return a sub-type of the type returned by the overridden method (i.e. super class’s method).

So, first check whether the return type of the overriding method is a subtype. For example, if the overriding method returns List, the overridden method can return ArrayList but not Object.

Next, you need to check the type specification of generic types. This is a bit complicated. To determine this, you must remember the following hierarchy of subtypes. Assuming that S is a sub type of T and <<< means “is a subtype of”, here are the two hierarchies:

Hierarchy 1 : A<S> <<< AS> <<< A
Example: Since Integer is a subtype of Number, List<Integer> is a subtype of List and List is a subtype of A. Thus, if an overridden method returns List, the overriding method can return List<Integer> but not List<Number> or List.

Hierarchy 2 : A <<< A <<< A
Example: List<Number> is a subtype of ListNumber> and ListNumber> is a subtype of AInteger> Thus, if an overridden method returns ListNumber>, the overriding method can return List<Number> but not List<Integer> or ListInteger>.

It is important to understand that List<Integer> is not a subtype of Number


继承的错误实例

class A{   
protected int i;   
A(int i) {    
this.i = i;    
}  } 

//1 : Insert code here


错误答案
class B extends A {}

正确插入答案
class B { B() {} }

错误答案解析

Since class B does not have any constructor, the compiler will try to insert the default constructor, which will look like this:
B(){ super(); }
//Notice that it is trying to call the no args constructor of the super class, A.
Since A doesn’t have any no-args constructor, the above code will fail to compile.

Notice that class A does not define a no-argument constructor. Also note that the class B does not define a constructor. Thus, class B relies on the default constructor B(). Class B’s default constructor looks like this:
B() {} //It is not public because class B is not public

However, Constructors implicitly (if an explicit call to the superclass’s constructor is not present) call their superclass’s constructor super(). So, class B’s default constructor actually looks like this:
B() {
super();
}

Now, since class A does not define a no-argument constructor the above code will not compile. However, class B would be correct if changed to:
class B extends A {
B() {
super(1); // pass it any integer
}
// or
B(int number) {
super(number);
}
}
You could also add a no-argument constructor to class A and leave class B as is.

Overload

It is illegal for a class to have two methods having same name and having same type of input parameters in the same order. 需要看方法名和形参的类型是否相同
Name of the input variables and return type of the method are not looked into. 形参的名字和返回类型不需要看

抽象类

有抽象类不一定有抽象方法,有抽象方法一定是抽象类
An abstract method cannot have a method body. {} constitutes a valid method body.

A class is uninstantiable if the class is declared abstract.
If a method has been declared as abstract, it cannot provide an implementation (i.e. it cannot have a method body ) and the class containing that method must be declared abstract).
If a method is not declared abstract, it must provide a method body (the class can be abstract but not necessarily so). If any method in a class is declared abstract, then the whole class must be declared abstract.
An class can still be made abstract even if it has no abstract method.

类的继承和方法的使用

  1. The overriding method may choose to have no throws clause even if the overridden method has a throws clause. Thus, the method m in YYY is valid.
  2. Whether a call needs to be wrapped in a try/catch or whether the enclosing method requires a throws clause depends on the class of the reference and not the class of the actual object.(依赖于类的引用,不是实际的对象) This is because it is the compiler that checks whether a call needs to have exception handling and the compiler knows only about the declared class of a variable. It doesn’t know about the actual object referred to by that variable (which is known only to JVM at run time).

Here, if you define obj of type XXX, the call obj.m() will have to be wrapped into a try/catch because main() doesn’t have a throws clause. But if you define obj of class YYY, there is no need of try catch because YYY’s m() does not throw an exception. Now, if the declared class of obj is YYY, you cannot assign it an object of class XXX because XXX is a superclass of YYY. So the only option left is to do: YYY obj = new YYY();

Example

class XXX{     
public void m() throws Exception{         
throw new Exception();     
} 
} 
class YYY extends XXX{     
public void m(){ }         
 public static void main(String[] args) {         
 ________  obj = new ______();         //正确做法 YYY   YYY, 错误做法  XXX  YYY 
 obj.m();     
 } }

构造方法 Constructor

  1. A final instance field of a class must be initialized during the initialization of an instance. This means that either it must be initialized in an instance initializer (because an instance initializer is executed before each constructor) or it must be initialized in every constructor.
  1. Unlike methods, a constructor cannot be abstract, static, final, native, or synchronized. A constructor is not inherited, so there is no need to declare it final and an abstract constructor could never be implemented.
  1. A constructor is always invoked on an object, so it makes no sense for a constructor to be static. There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work. The lack of native constructors is an arbitrary language design choice that makes it easy for an implementation of the Java Virtual Machine to verify that superclass constructors are always properly invoked during object creation.

Constructors cannot have empty bodies (i.e. they cannot be abstract), Constructors cannot return anything. Not even void.
You may apply public, private, and protected modifiers to a constructor. But not static, final, synchronized, native and abstract. It can also be package private i.e. without any access modifier.

String API

Example

public class TestClass{          
public static void main(String[] args) {          
System.out.println(getMsg((char)10));     
 }      
 public static String getMsg(char x){         
 String msg = "Input value must be ";         
 msg = msg.concat("smaller than X");         
 msg.replace('X', x);         
 String rest = " and larger than 0";        
 msg.concat(rest);         
 return msg;     
  	} 
  }
  //Input value must be smaller than X

Explanation

Remember that a String once created cannot be changed. Therefore, when you call replace or concat methods on a String, a new String object is created. The old String remains as it is. Here, the first call to concat returns a new String object containing “Input value must be smaller than X” and it is assigned back to msg. The original String referred to by msg is now lost (i.e. there is no reference to it anymore).

The first call to replace also creates a new String object but it is not assigned to any reference and is therefore lost and msg keeps pointing to the same String object. The same thing happens to the second call to concat. It create a new String object but it is not assigned back to msg, therefore, msg keeps pointing to the same object i.e. “Input value must be smaller than X”


Example String StringBuilder

public class Test{     
public static void stringTest(String s){         
s.replace('h', 's');     
}     
public static void stringBuilderTest(StringBuilder s){         
s.append("o");     
}     
public static void main(String[] args){         
String s = "hell";         
StringBuilder sb = new StringBuilder("well");         
stringTest(s);        
stringBuilderTest(sb);         
System.out.println(s + sb);     //it will print  hellwello
} 
}

Explanation

A String is immutable while a StringBuilder is not. So in stringTest(), “hell”.replace(‘h’, ‘s’) will produce a new String “sell” but will not affect the original String that was passed to the method. However, the append() method of StringBuilder appends to the original String object. So, “well” becomes “wello”.


There are 2 points to remember:

  1. replace(char oldChar, char newChar) method returns the same String object if both the parameters are same, i.e. if there is no change.
    Thus, “String” == “String”.replace(‘g’, ‘g’) will return true.
  2. replace(CharSequence oldSeq, CharSequence newSeq) method returns a new String object even if there is no change after replacement. Thus,
    “String” == “String”.replace(“g”, “g”) will return false.

method equalsIgnoreCase()

equalsIgnoreCase() method treats both cases (upper and lower) as same

Example

"HELLO world".equalsIgnoreCase("hello world")

Method compareTo()

Notice that the Strings differ at the first position. The value returned by compareTo is (Unicode value of the left hand side - Unicode value of the right hand side).

Although not required for the exam, it is good to know that for English alphabets, the unicode value of any lower case letter is always 32 more than the unicode value of the same letter in upper case. So, ‘a’ - ‘A’ or ‘h’ - ‘H’ is 32.

Example

"hello world".compareTo("Hello world") >0

compareTo() does a lexicographical (like a dictionary) comparison. It stops at the first place where the strings have different letters.
If left hand side is bigger, it returns a positive number otherwise it returns a negative number. The value is equal to the difference of their unicode values.
If there is no difference then it returns zero. In this case, it will return ( ‘h’ - ‘H’) which is 32.

Method compare()

public static int compare(int[] a, int[] b)
Compares two int arrays lexicographically. If the two arrays share a common prefix then the lexicographic comparison is the result of comparing two elements, as if by Integer.compare(int, int), at an index within the respective arrays that is the prefix length. Otherwise, one array is a proper prefix of the other and, lexicographic comparison is the result of comparing the two array lengths. (See mismatch(int[], int[]) for the definition of a common and proper prefix.)

A null array reference is considered lexicographically less than a non-null array reference. Two null array references are considered equal.

It returns 0 if the first and second array are equal and contain the same elements in the same order; a value less than 0 if the first array is lexicographically less than the second array; and a value greater than 0 if the first array is lexicographically greater than the second array.

For example, the following code will print -1 because the first array has smaller integer at index 2.

int[] ia1 = { 0, 1, 2, 6}; 
int[] ia2 = { 0, 1, 5}; 
System.out.print(Arrays.compare(ia1, ia2)); //prints -1

Observe that the returned value (-1) does not depend on the amount of different between the two elements (2 - 5 is -3).

         char[] a = { 'h', 'e', 'l', 'l'};       
         char[] b = { };                  
         int x = Arrays.compare(a, b);        
         int y =     Arrays.mismatch(a, b);         
         System.out.println(x+" "+y);  //print 4 0

Since the second array is a proper prefix of the first array, compare() will return a positive number and the number will be the same as the difference in the number of elements in both the arrays i.e 4-0 = 4.

Since the two arrays are differ at index 0, mismatch will return 0.

Method mismatch()

public static int mismatch(int[] a, int[] b)
Finds and returns the index of the first mismatch between two int arrays, otherwise return -1 if no mismatch is found. The index will be in the range of 0 (inclusive) up to the length (inclusive) of the smaller array.

If the two arrays share a common prefix then the returned index is the length of the common prefix and it follows that there is a mismatch between the two elements at that index within the respective arrays. If one array is a proper prefix of the other then the returned index is the length of the smaller array and it follows that the index is only valid for the larger array. Otherwise, there is no mismatch.

Two non-null arrays, a and b, share a common prefix of length pl if the following expression is true:

 pl >= 0 &&  
 pl < Math.min(a.length, b.length) &&  
 Arrays.equals(a, 0, pl, b, 0, pl) &&      
 a[pl] != b[pl]

Note that a common prefix length of 0 indicates that the first elements from each array mismatch. Two non-null arrays, a and b, share a proper prefix if the following expression is true:

     a.length != b.length &&      
     Arrays.equals(a, 0, Math.min(a.length, b.length),                    
     						b, 0, Math.min(a.length, b.length)

For example, the following code will print 2 because the arrays differ at index 2

int[] ia1 = { 0, 1, 2, 6}; 
int[] ia2 = { 0, 1, 5};
System.out.println(Arrays.mismatch(ia1, ia2)); //prints 2

Observe that 2 is also the length of the prefix, which is {0, 1}.
You should now go through the JavaDoc API description of the various overloaded compare and mismatch methods. You will notice that they all work in the same basic fashion.

String and StringBuilder method

String is immutable while StringBuilder is not. So no matter what you do in replaceString() method, the original String that was passed to it will not change.
On the other hand, StringBuilder methods, such as replace or append, change the StringBuilder itself. So, ‘c’ is appended to java in replaceStringBuilder() method.

Example

public class Sample{
   public static void main(String[] args)  {
     String s1 = new String("java");
     StringBuilder s2 = new StringBuilder("java");
     replaceString(s1);
     replaceStringBuilder(s2);
     System.out.println(s1 + s2);   //   it  will print javajavac
  }
  static void replaceString(String s) {
     s = s.replace('j', 'l');
  }
  static void replaceStringBuilder(StringBuilder s) {
     s.append("c");
  }
}

var使用

1.‘var’ is not allowed in a compound declaration复合声明. In other words, you can define only one variable using var.
2. Variables declared with var must be assigned a value in the declaration itself because without the value, the compiler will not be able to infer the type of the variable.
3. var declarations are allowed only for local variables (i.e. variables defined inside method body) and in for loops (for example, for(var i = 0; i<10; i++){ } ). 不可以声明为实例变量,只能声明局部变量,且必须赋值。It is not allowed to declareclass/instance fields, method parameters, or method return types.
4.You can never apply square brackets to var. var[] implies that the type of the element of the array is var, which is not allowed.

Remember that static and instance variables are automatically assigned a value even if you don’t initialize them explicitly but local variables must be initialized explicitly before they are used.静态和实例变量会自动赋值,假如你没有赋予他们初始值。但是局部变量必须赋值

Loop,Switch,For,While

In Java, a while or do/while construct takes an expression that returns a boolean.
But unlike a for loop, you cannot put instantiation and increment sections in the while condition. Therefore, for(int k=5;k<7;) is valid but while(int k=5;k<7;) is not.

Double/float/long/boolean cannot be used in a switch statement.

for

for is a keyword and so cannot be used as a label. But you can use any other identifier as a label.

For example,

The following code is valid even though String is a class name and String is also used as an identifier!

  String String = "";   //This is valid.
     String : for(int i = 0; i< 10; i++) //This is valid too!
     {
        for (int j = 0; j< 10; j++){
             if ( i+ j > 10 )  break String;
        }
       System.out.println( "hello");
      }


//It will print hello 2 times.

Switch

Every statement in a case block must belong to a case or to the default label.
You cannot have unlabeled block of code inside a switch block. Any code block must succeed a case label (or default label).

Exception异常

When you use System.out.println(exception), a stack trace is not printed. Just the name of the exception class and the message is printed.
When you use exception.printStackTrace(), a complete chain of the names of the methods called, along with the line numbers, is printed. It contains the names of the methods in the chain of method calls that led to the place where the exception was created going back up to the point where the thread, in which the exception was created, was started.

Normal execution will not resume if an exception is uncaught by a method. The exception will propagate up the method invocation stack until some method handles it. If no one handles it then the exception will be handled by the JVM and the JVM will terminate that thread.

An (子类覆盖方法)overriding method only needs to declare that it can throw a subset of the exceptions the overridden method can throw. Having no throws clause in the overriding method is OK.

It can throw any subset of the exceptions thrown by overridden class.

Any remaining code of the method will not be executed. Further, any uncaught exception will cause the JVM to kill the thread

If “MyException” is an unchecked exception, then there is no need of a try block. Even if MyException is a checked exception, the method could simply declare it in its throws clause instead of wrapping the call in a try block.

如果父类被覆盖方法 生命一个受检异常(checked exception),则调用这个被覆盖方法的调用类的方法也需要声明throws的clause(相同的受检异常或者子类异常(异常的子类))或者使用try catch。

Example

 //in file A.java 
 public class A{   
 protected void m() throws SomeException{
 } 
 }  
 //in file B.java 
 public class B extends A{    
 public void m(){         //此处并没有声明抛出一个异常
 } 
 } 
  //in file TestClass.java 
  public class TestClass{    
  public static void main(String[] args){       
  //insert code here. //1    
  } 
  }

//Wrong insert 
A a = new B(); 
a.m()  ;
/*
A's m() declares 'throws SomeException', which is a checked exception, while the main() method doesn't. So a.m() must be wrapped in a try/catch block.   
*/

Correct insert 
A a = new B(); 
( ( B) a ).m();
/*
Due to explicit casting of 'a' to B, the compiler knows that 'a' will point to an object of class B (or its subclass), whose method m() does not throw an exception. So there is no need for a try catch block here.
*/

Handling Exception Example

class MyException extends Exception{} 
class MyException1 extends MyException{} 
class MyException2 extends MyException{} 
class MyException3 extends MyException2{}  

and the following code:        
try{          
  //code that could potentially throw any of the above mentioned exceptions      
 }       
 INSERT CODE HERE

//Correct Insertion Example

catch(MyException3 me3){ } catch(Exception e){  }

//Incorrectly Insertion Example


catch(MyException|MyException3 e){  }   

// Exceptions specified in a multi-catch block must not have a parent-child  (or ancestor/successor) relationship

//Incorrectly Insertion Example


catch(MyException2 me2){ } catch(MyException3 me3){ }

//MyException3 extends MyException2 and is thus more specific than MyException2. 
Therefore, catch clause for MyException3 must appear before MyException2.

//Incorrectly Insertion Example

catch(MyException|MyException1|MyException2|MyException3 e){  }

//Incorrectly Insertion Example


catch(Throwable t){ } catch(MyException3 me3){ }

//Throwable is the root of all exceptions. Since, Throwable is an ancestor class of MyException3, MyException3 is more specific than Throwable, and so, catch clause for MyException3 must appear before Throwable.

Incorrect Insertion Example

catch(MyException|MyException1|MyException2|MyException3 e){  }

//Exceptions specified in a multi-catch block must not have a parent-child (or ancestor/successor) relationship.

Explanations

You can visualize multiple catch blocks like a series of baskets put one below the other. If you put a bigger basket on the top, the smaller basket below will not be able to catch anything. Similarly, if you put a catch block with a generic exception (i.e. a super class exception) above a specific exception (a sub class exception), then the lower catch block will never catch any exception. That is why, a catch block with more specific exception can only be put before a catch block with less specific exception.

Here is an example. Assume that E1 extends Exception and E2 extends E1. This means, E2 is more specific than E1 and E1 is more specific than Exception. The catch blocks must then be placed like this:

try{   //some code that might throw any of the three exceptions } 
catch(E2 e2){ } 
catch(E1 e1){ } 
catch(Exception e){ }  
//   If the exception classes are unrelated, then the order is not important.

Rule for overriding a method is opposite to the rule for constructors.
覆盖方法的规则与构造函数的规则相反。

The rule for overriding a method is opposite to the rule for constructors.
An overriding method cannot throw a superclass exception, while a constructor of a subclass cannot throw subclass exception (Assuming that the same exception or its super class is not present in the subclass constructor’s throws clause).

For example:

class A{     
public A() throws IOException{ }       
void m() throws IOException{ }   
}    

class B extends A{     

//IOException is valid here, but FileNotFoundException is invalid     
public B() throws IOException{ }      

//FileNotFoundException is valid here, but Exception is invalid     
void m() throws FileNotFoundException{ } 
}


//(Note: FileNotFoundException is a subclass of IOException, 
//which is a subclass of Exception) If the subclass constructor's throws clause includes the same exception or its superclass, then it can throw any other exception as //well.

Explanation

As PortConnector has only one constructor, there is only one way to instantiate it. Now, to instantiate any subclass of PortConnector, the subclass’s constructor should call super(int).
But that throws IOException. And so this exception (or its super class) must be defined in the throws clause of subclass’s constructor. Note that you cannot do something like:

public CleanConnector(){    
try{ super(); 
}
catch(Exception e){} //WRONG : call to super must be first statement in constructor }

Remember: Constructor must declare all the checked exceptions declared in the base constructor (or the super classes of the checked exceptions).
They may add other exceptions as well. This behavior is exactly opposite from that of methods. The overriding method cannot throw any checked exception other than what the overridden method throws. It may throw subclasses of those exceptions as well.

Primitive Data

Example

public class TestClass{        
public static void main(String[] args){      
short s = 9;      
//1   
 } }

//wrong code insert

Short k = new Short(9); System.out.println(k instanceof Short);

/*
9 is considered an int and there is no constructor in Short that takes an int. 
Short s = new Short( (short) 9 ); will work.
*/


//correct code insert
int i = 9; System.out.println(s == i);   
//or  
Integer i = 9; System.out.println( s == i );
/*
Any two numeric primitives can be compared using == operator.
Even a numeric primitive and a primitive wrapper (for example, an int with a Short or a Double) can be compared. However, two wrappers of different types (for example, an Integer and a Short) cannot be compared using ==.
*/

Java does not permit implicit narrowing from double to float. Implicit narrowing is permitted only among byte, char, short, and int.
Java不允许从double隐式收缩为float。隐式窄化只允许在字节、char、short和int之间使用。

Method 使用 Example

class TestClass{
    void probe(int... x) { System.out.println("In ..."); }  //1
    
    void probe(Integer x) { System.out.println("In Integer"); } //2
    
    void probe(long x) { System.out.println("In long"); } //3 
    
    void probe(Long x) { System.out.println("In LONG"); } //4
    
    public static void main(String[] args){
        Integer a = 4; new TestClass().probe(a); //5
        int b = 4; new TestClass().probe(b); //6
    }
}
//In Integer and In long
//It will not compile, if //1, //2, and //3 are commented out.

Explanation

To answer this type of questions, you need to know the following rules:

  1. The compiler always tries to choose the most specific method available with least number of modifications to the arguments.
  2. Java designers have decided that old code should work exactly as it used to work before boxing-unboxing functionality became available.
  3. Widening is preferred to boxing/unboxing (because of rule 2), which in turn, is preferred over var-args.

Thus,

  1. probe(Integer) will be bound to probe(Integer) (exact match). If that is not available, it will be bound to probe(long), and then with probe(int…) in that order of preference.
    probe(long) is preferred over probe(int…) because unboxing an Integer gives an int and in pre 1.5 code probe(long) is compatible with an int (Rule 2).
    It is never bound to probe(Long ) because Integer and Long are different object types and there is no IS-A relation between them. (This holds true for any two wrapper classes). It could, however, be bound to probe(Object ) (if it existed), because Integer IS-A Object.
  2. probe(int) is bound to probe(long) (because of Rule 2) , then to probe(Integer ) because boxing an int qives you an Integer, which matches exactly to probe(Integer), and then to probe(int…).
    It is never bound to probe(Long ) because int is not compatible with Long.

instance variable static variable 实例变量 和类变量

Example

class StaticTest{
    
    void m1(){
        StaticTest.m2();  // 1
        m4();             // 2
        StaticTest.m3();  // 3   will fail to compile
    }
    
    static void m2(){ }  // 4
    
    void m3(){
        m1();            // 5
        m2();            // 6
        StaticTest.m1(); // 7   will fail to compile
    }
    
    static void m4(){ }
}

To call an instance method you need a reference that points to the object on which you want to call that method. Now, within an instance method a reference named “this” pointing to the current object is always available. So to call another instance method from within an instance method, you can either use the this reference explicitly (for example, you may call this.m3() from within m1) , or leave out the this reference altogether (for example, you can directly call m3() from within m1()) because the compiler automatically adds the “this.” part implicitly. The “this” variable is available only within an instance method and not in static methods because static methods are not invoked within the context of an object of that class.

You can call a static method of a class from either a static or an instance method of the same class . (同一个类下,你可以从他的类方法或者实例方法去call他的其他的类方法)。No object reference is required. You can call it by using the name of the class or you can omit that as well. To call a static method of another class, you must use the name of the other class, for example OtherClass.staticMethod();

At //3, you are trying to call an instance method from another instance method. Therefore, you need to either specify an object reference or you can rely on this if you omit it. However, you cannot do StaticTest.m3() because StaticTest is not a valid reference that points to an object of class StaticTest. Same thing happens at //7.

Modifier修饰符

Access modifiers (public/private/protected) are valid only inside the scope of a class, not of a method.

Remember, return type (i.e. void) and method name (i.e. main) are NEVER separated. They are always together.

错误示例

public void static main(String args[ ])    //错误表达,由于返回类型没有跟方法名在一起

For java cert exam

JVM to execute a class using the standard main method, the accessibility of the main method must be public.

Class命名规范

Example

//in file main.java 
class anothermain{    
	public static void main(String[] args) {        
	System.out.println("hello2");    
	} 
} 
class main {    
	public final static void main(String[] args) {        
	System.out.println("hello");    
	} 
}

Observe that there is no public class in file main.java. This is ok. It is not necessary for a java file to have a public class. The requirement is that if a class (or enum) is public then that class (or enum) must be defined in a file by the same name and that there can be only one public class (or enum) in a file. 类名是public,则此类的文件名必须与类名字相同。

class main’s main method will be executed. final is a valid modifier for the standard main method.

Note that final means a method cannot be overridden. Although static methods can never be overridden (they can be hidden), making a static method final prevents the subclass from implementing the same static method.

Array[]
Example

 public class TestClass{    
 	public static void main(String args[] ){       
 		int i = 0 ;       
		 int[] iA = {10, 20} ;      
		 iA[i] = i = 30 ;       
 System.out.println(""+ iA[ 0 ] + " " + iA[ 1 ] + "  "+i) ;     //It will print 30 20 30
 	} 
 }

The statement iA[i] = i = 30 ; will be processed as follows:
iA[i] = i = 30; => iA[0] = i = 30 ; => i = 30; iA[0] = i ; => iA[0] = 30 ;

Here is what JLS says on this:
1 Evaluate Left-Hand Operand First 自左向右
2 Evaluate Operands before Operation
3 Evaluation Respects Parentheses and Precedence
4 Argument Lists are Evaluated Left-to-Right

For Arrays: First, the dimension expressions are evaluated, left-to-right. If any of the expression evaluations completes abruptly, the expressions to the right of it are not evaluated.

Garbage Collection

Example

class M { } 
class N{    
private M m = new M();    
public void makeItNull(M pM){       
pM = null;   
 }    
 public void makeThisNull(){       
 makeItNull(m);   
 }    
 public static void main(String[] args){       
 N n = new N();       
 n.makeThisNull();    
 } 
 }   
//There are no instances of M to be garbage collected till the program ends.

Explanation

n.makeThisNull() internally calls makeItNull(m), which sets is method parameter pM to null. However, remember that, in Java, every call is pass by value.
Therefore, when makeItNull(m) is called, the value of m is passed to the method and not m itself. The method parameter pM is therefore is not same as m but a new variable that points to the same object as the one pointed to by m.
It is that variable pM which is set to null. The original m still keeps pointing to the same object as it was. Therefore, the instance of M will not be marked for garbage collection.
pM is just a method parameter (a copy of the original reference) that is passed to makeItNull(). So setting it to null will not affect the original variable.

Summaries

1. An object can be made eligible for garbage collection by making sure there are no references pointing to that object.
2. You cannot directly invoke the garbage collector. You can suggest the JVM to perform garbage collection by calling System.gc();

你可能感兴趣的:(Java,Java,JDK11)