[JavaSE] Lambda, Int and Integer
1, Inner class and anonymous inner class
Internal classes are classes defined in classes. Their main function is to put logically related classes together. Anonymous inner class is a special inner class. It has no class name. When defining a class or implementing an interface, it generates an object of the class. Because it will not be used elsewhere, it does not need to take a name, so it is called anonymous inner class.
1. Inner class
The following example shows that the inner class is a class contained in the class and can be regarded as a member of the outer class, so it is also called a member class.
public class Out { private int age;//Declare a private member variable of an external class public class Student{//Declare inner class String name; //Access the member variable name of the inner class public Student(String n,int a){ name = n; //Access internal class name age = a; //Accessing external classes } public void output(){ System.out.println("full name:"+this.name+";Age:"+age); } } public void output(){ Student stu = new Student("Liu Yang",24); //Create internal class object stu stu.output(); } public static void main(String[] args) { Out g = new Out(); g.output(); } }
① JVM level analysis
In terms of file management, after the internal class is compiled, the generated file name is "external class name" $Internal class name.class". Therefore, the above cases will produce two files after variation: Out.class and Out$Student.class"
A reference to an external class object is saved in the internal class object. When accessing a variable in the member method of the internal class, if the variable is not defined in the method and the internal class, the call will be passed to the reference of the external class object saved in the internal class. Call this variable through the reference of the external class object in the internal class The same is true for calling methods of external classes.
Distribution of the above codes in memory
② Properties of inner classes
Java takes an internal class as a member, just like a member variable or member method. An internal class can be declared private or protected. Therefore, the access principle between an internal class and an external class is: in an external class, the members of the internal class can be referenced through an object of the internal class. On the contrary, the members of its external class can be directly referenced in the internal class, including static members Instance members and private members. Internal classes can also be called from outside the external class by creating objects, but the internal class must be declared public.
2. Anonymous inner class
Syntax format:
new TypeName(){//TypeName is a parent class name or interface name, and parameters are not allowed in parentheses' () ' //Class body of anonymous class } TypeName Obj = new TypeName(){ //Class body of anonymous class } someMethod(new TypeName(){ //Class body of anonymous class });
Case:
public class TestInnerClass{ public static void main(String[] args){ ( new Inner(){ void setName(String n){ name = n; System.out.println("full name:"+name); } } ).setName("Zhang Hua"); } static class Inner{//Define internal classes String name; } }
Case: use the interface to create anonymous internal class objects and implement the abstract methods in the interface
interface IShape{ void shape(); } class MyType{ public void outShape(IShape s){//Method parameters are variables of interface type s.shape(); } } public class App13_5 { public static void main(String[] args) { MyType a = new MyType();//Create an object of the MyType class a a.outShape(new IShape() {//Create an anonymous internal object with the interface name IShape @Override //The shape() method in the interface must be overridden public void shape() { System.out.println("I can be any shape"); } }); } }
2, Functional interfaces and Lambda expressions
Lambda expression refers to a simplified definition form applied in the interface environment with only one abstract method. It can be used to solve the complex problem of anonymous internal class definition.
1. Functional interface (FI)
It refers to the interface containing an abstract method, so it is also called abstract method interface. Every lambda expression is a functional interface. Lambda expression can be regarded as an object of an anonymous inner class that implements the functional interface.
In order for the compiler to ensure that an interface meets the requirements of a functional interface, Java8 provides the @ FunctionalInterface annotation. For example, the Runnable interface is a functional interface. The following is its annotation method:
If the interface uses @ FunctionalInterface for annotation, but it is not a functional interface, an error will occur during compilation. A functional interface can only have one abstract method to be implemented, except for the following special cases.
-
In the functional interface, there are methods covered in the Object class, i.e. equals(), toString(), hashCode(), etc.
-
For example, the Comparator interface is a functional interface:
-
The interface declares multiple methods, but the equals() method is a method in the Object class.
- Intelligent life in functional interfaces is an abstract method, but static methods and default methods (i.e. methods decorated with default) do not belong to abstract methods. Therefore, static methods and default methods can be defined in functional interfaces, such as Comparator interface
@FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> thenComparing(Comparator<? super T> other) { Objects.requireNonNull(other); return (Comparator<T> & Serializable) (c1, c2) -> { int res = compare(c1, c2); return (res != 0) ? res : other.compare(c1, c2); }; } public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) { return new Comparators.NullComparator<>(false, comparator); }
2. Lambda expression
A Lambda expression is a piece of code that can be passed to a method. It can open a statement or a code. Because a method name is not required, a Lambda expression is an anonymous method, that is, a method without a method name.
Any Lambda expression in Java must have a functional interface for. This is precisely because of this requirement. However, in order to distinguish the interface used by Lambda expression, it is better to use the annotation @ FunctionalInterface annotation declaration, which means that this interface is a functional interface.
Functional interfaces are important because Lambda expressions can be used to create an object equivalent to anonymous inner classes. That's why Lambda expressions can be regarded as anonymous inner classes using reduced syntax.
① Simplify the case of the above anonymous inner class
a.outShape( () -> { System.out.println("I can be any shape"); } );
② Grammar
Compared with anonymous inner classes, the syntax of lambda expressions omits the interface type and method name, - > the parameter list is on the left and the method body is on the right. Lambda expressions are usually composed of parameter list, arrow and method body:
(Type 1 parameter 1, Type 2 parameter 2, ...) -> {Method body}
- The parameters in the parameter list are formal parameters of anonymous methods, i.e. input parameters. The parameter list allows to omit the type of formal parameters, that is, the data type of a parameter can be explicitly declared or inferred from the type inference function of the compiler; when the parameter is a inference type, the data type of the parameter will be automatically inferred by the JVM according to the context.
- The method body can be a single expression or a team composed of multiple statements. If there is only one statement, the curly braces of the method body can be omitted. If there is only one return statement, the return keyword can also be omitted.
- If the statement with the return keyword is omitted, the Lambda expression will automatically return the result value of the statement.
- If there are no parameters, you can write only one parenthesis.
- If the Lambda expression has only one parameter and does not give an explicit data type, the parentheses can be omitted.
3. Lambda expressions as arguments to methods
In order to pass a Lambda expression as a parameter, the parameter that accepts the Lambda expression must be a functional interface type compatible with the Lambda expression.
Example:
@FunctionalInterface interface StringFunc{//Define functional interfaces public String func(String s);//Abstract method } public class App13_9 { static String sop(StringFunc sf,String s){//Static method return sf.func(s); } public static void main(String[] args) { String outStr,inStr = "Lambda expression good"; System.out.println("Source string:"+inStr); outStr =sop ((str)->str.toUpperCase(),inStr);//Converts the string inStr to uppercase System.out.println("After converting to large characters:"+outStr); outStr =sop((str->{ String result = ""; for (int i = 0; i <str.length() ; i++) if (str.charAt(i)!=' ') result += str.charAt(i); return result; }),inStr); System.out.println("String without spaces:"+outStr); } }
- The static method of sop has two parameters. The first parameter sf is the functional interface type StringFunc, so it can accept references to any StringFunc instance, including the instance created by Lambda expression. The second parameter s is the String type, that is, the String to be operated.
- A large number of functional interfaces are defined in the java.util.function package, such as functional interfaces function < T, R > and bifunction < T, u, R > and so on. It is easier to write Lambda expressions with them.
3, Method reference
After Java 8, the double colon "::" operator is added for method reference. A method reference is not a method call. If the passed Lambda expression has an implemented method, you can use a method reference instead of the Lambda expression. Method reference can be understood as another form of Lambda expression. Method reference uses double colon operator "::" to simplify Lambda expression.
① Reference form
- Object name:: instance method name
- Class name:: static method name
- Class name:: instance method name
- Class name:: new
explain
- In the fourth reference construction method, the right side can only be the keyword new. The other three can be parenthesized
- The first two reference methods are used when there is only one parameter. Method references are equivalent to Lambda expressions that provide method parameters. For example, System.out::print is equivalent to System.out.print(s). The third reference method is used for more than two parameters. The first parameter is the object calling the method.
② Case description
-
The first is anonymous inner class
Consumer<String> con = new Consumer<String>{ @Override public ovid accept(String str){ System.out.println(str); } }
-
Second: Lambda expression
Consumer<String> con = str ->System.out.println(str)//Create instance con.accept("I am a consumer interface");
-
Third: method reference
Consumer<String> con = System.out::println con.accept("I am a consumer interface");
4, Int and Integer
- Integer is the wrapper class of int; Int is the basic data type;
- Integer variable can only be used after instantiation; int variables are not required;
- Integer is actually a reference to the object, pointing to the integer object of this new; int is the data value stored directly;
- The default value of Integer is null; The default value of int is 0.
Reference blog:
https://blog.csdn.net/chenliguan/article/details/53888018
-
Because the Integer variable is actually a reference to an Integer object, the two Integer variables generated by new are never equal (because new generates two objects with different memory addresses)
-
When comparing Integer variables with int variables, as long as the values of the two variables are equal, the result is true (because when comparing wrapper class Integer with basic data type int, java will automatically unpack it as int and then compare it, which will actually become the comparison of two int variables)
-
When comparing the non new generated Integer variable with the variable generated by new Integer(), the result is false. Because the Integer variable generated by non new points to the Integer object stored in the cache array in the static constant pool, and the variable generated by new Integer () points to the new object in the heap, their object references (addresses) in memory are different.
-
Memory structure of JVM
-
Integer i = new Integer(100); Integer j = 100; System.out.print(i == j); //false
-
-
For two Integer objects not generated by new, if the values of the two variables are between - 128 and 127, the comparison result is true. If the values of the two variables are not in this interval, the comparison result is false
-
Integer i = 100; Integer j = 100; System.out.print(i == j); //true Integer i = 128; Integer j = 128; System.out.print(i == j); //false
-
java is compiling Integer i = 100; It will be translated into Integer i = Integer.valueOf(100). In the java API, the valueOf of Integer type is defined as follows. The number between - 128 and 127 will be cached. When Integer i = 127, the Integer object 127 will be cached. When Integer j = 127 is written next time, it will be directly fetched from the cache and will not be new.
-
5, LeetCode-977. Square of ordered array
① Title Stem
② Int array to Integer array
③ Code implementation
public class Solution { public static int[] sortedSquares(int[] nums) { //Convert to packaging class Integer[] nums2 = Arrays.stream(nums).boxed().toArray(Integer[]::new); //Lambda expression Arrays.sort(nums2, (o1, o2) -> Math.abs(o1) > Math.abs(o2) ? 1 : -1); // lambda expression //Method reference nums = Arrays.stream(nums2).mapToInt(Integer::valueOf).toArray(); for (int i = 0; i < nums.length; i++) nums[i] *= nums[i]; return nums; } }