In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article is mainly about "what's the difference between jdk1.4 and jdk1.5". Interested friends might as well take a look. The method introduced in this paper is simple, fast and practical. Now let the editor take you to learn "what's the difference between jdk1.4 and jdk1.5?"
1. Generics
2 automatic packing / unpacking
3 for-each
4 static import
5 variable length parameter [@ more@]
1. Generics 1.4.Container classes in the java util package contain Object objects. You can install specific types, but cast them, which may result in runtime errors.
Example: original ArrayList list=new ArrayList ()
List.add (new Integer (3))
List.add (new Integer (4))
Int I = ((Integer) (list.get (0) .parseInt ()
It's a lot of trouble.
Now ArrayListlist=new ArrayList ()
List.add (new Integer (3))
List.add (new Integer (4))
Int i=list.get (0) .parseInt ()
Without Cast, run-time errors become compile-time errors, which is progress.
Similar to the template templete in C++. But the mechanism is different.
2 automatic packing / unpacking
It's just an example.
The last sentence can be changed to
Int i=list.get (0)
The original type and the corresponding wrapper class need not be explicitly converted, so it is convenient.
3 for-each
Enhancement of the cycle
Int a [] = {.}; / / initialize, briefly
For (int iVLA)
{
.
}
Do not use the previous ipassport 0 share i4 static import
Used to adjust Java.math
Math.sqrt ()
Now, static import java.lang.Math.sqrt,
Then sqrt ()
It is equivalent to having this method in your own class.
5 variable length parameter
Int sum (int... intlist)
{
Int i,sum
Sum=0
For (int iTuno Tinci 1) {
Exception e = (Exception) objects [1]
/ / Do something with the exception
}
}
The method signature should look like this, and the corresponding variable parameters should be declared using String and Exception, respectively:
Log.log (String message, Exception e, Object... Objects) {.}
Do not use variable parameters to break the type system. Use it only when you need to be strongly typed. PrintStream.printf () is an interesting exception to this rule: it provides type information as its first parameter so that those types can be accepted later.
Covariant return
The basic use of covariant returns is to avoid type casting when it is known that the return type of an implementation is more specific than API. In the following example, there is a Zoo interface that returns an Animal object. Our implementation returns an AnimalImpl object, but before JDK 1.5, an Animal object must be declared. :
Public interface Zoo {
Public Animal getAnimal ()
}
Public class ZooImpl implements Zoo {
Public Animal getAnimal () {
Return new AnimalImpl ()
}
}
The use of covariant returns replaces three anti-patterns:
Direct field access. To circumvent API restrictions, some implementations directly expose subclasses as fields:
ZooImpl._animal
Another form is to perform a downward conversion in the caller knowing that what is actually implemented is a specific subclass:
((AnimalImpl) ZooImpl.getAnimal ()) .implMethod ()
The last form I saw was a concrete method to avoid problems caused by a completely different signature:
ZooImpl._getAnimal ()
All three models have their own problems and limitations. Either it is not neat enough, or it exposes unnecessary implementation details.
Covariation
The covariant return pattern is neat, secure, and easy to maintain, and it does not require type casting or specific methods or fields:
Public AnimalImpl getAnimal () {
Return new AnimalImpl ()
}
Results of use:
ZooImpl.getAnimal () .implMethod ()
Use generics
We will look at generics from two perspectives: using generics and constructing generics. We won't discuss the obvious uses of List, Set, and Map. It is sufficient to know that generic collections are powerful and should be used frequently.
We will discuss the use of generic methods and the ways in which compilers infer types. Usually none of this will go wrong, but when something goes wrong, the error message can be very confusing, so you need to know how to fix these problems.
Generic method
In addition to generic types, Java 5 also introduces generic methods. In this example from java.util.Collections, a single element list is constructed. The element type of the new List is inferred from the type of the object passed in the method:
StaticListCollections.singletonList (to)
Example usage:
Public ListgetListOfOne () {
Return Collections.singletonList (1)
}
In the example usage, we pass in an int. So the return type of the method is List. The compiler deduces T as Integer. This is different from generic types because you usually do not need to specify type parameters explicitly.
This also shows the interaction between autoboxing and generics. The type parameter must be a reference type: that's why we get List instead of List.
Generic method without parameters
The emptyList () method is introduced with generics as a type-safe replacement for the EMPTY_LIST field in java.util.Collections:
StaticListCollections.emptyList ()
Example usage:
Public ListgetNoIntegers () {
Return Collections.emptyList ()
}
Unlike the previous example, this method has no parameters, so how does the compiler infer the type of T? Basically, it will try to use the parameters once. If it doesn't work, it tries to use the return or assignment type again. In this case, List is returned, so T is inferred to be Integer.
What if a generic method is called at a location other than a return statement or an assignment statement? Then the compiler will not be able to perform the second transfer of type inference. In the following example, emptyList () is called from within the conditional operator:
Public ListgetNoIntegers () {
Return x? Collections.emptyList (): null
}
Because the compiler cannot see the return context and cannot infer T, it abandons and takes Object. You will see an error message, such as: "unable to convert List to List."
To fix this error, you should explicitly pass type parameters to the method call. In this way, the compiler does not try to infer type parameters and can get the correct results:
Return x? Collections.emptyList (): null
Another place where this often happens is in method calls. You also need to use this syntax if a method takes a List parameter and you need to call the passed emptyList () for that parameter.
Outside the collection
Here are three examples of generic types, which are not collections, but rather use generics in a novel way. All three examples come from the standard Java library:
Class
Class is parameterized on the type of the class. This makes it possible to construct a newInstance without type casting.
Comparable
Comparable is parameterized by the actual comparison type. This provides stronger typing when compareTo () is called. For example, String implements Comparable. Calling compareTo () on anything other than String will fail at compile time.
Enum
Enum is parameterized by enumerated types. An enumerated type named Color extends Enum. The getDeclaringClass () method returns a class object of enumerated type, which in this case is a Color object. It is different from getClass (), which may return a nameless class.
Wildcard character
The most complex part of generics is the understanding of wildcards. We will discuss the three types of wildcards and their uses.
First, let's take a look at how arrays work. You can assign values to a Number [] from an Integer []. If you try to write a Float to Number [], you can compile, but fail at run time, and an ArrayStoreException appears:
Integer [] ia = new Integer [5]
Number [] na = ia
Na [0] = 0.5; / / compiles, but fails at runtime
If you try to convert the example directly to generics, it will fail at compile time because assignments are not allowed:
ListiList = new ArrayList ()
ListnList = iList; / / not allowed
NList.add (0.5)
If you use generics, you will not encounter a runtime ClassCastException as long as the code is compiled without warnings.
Upper limit wildcard
What we want is a list of unknown exact element types, which is different from arrays.
List is a list whose element type is the concrete type Number.
List is a list of unknown exact element types. It is Number or its subtype.
Upper limit
If we update the original example and assign a value to List, then the assignment will be successful now:
ListiList = new ArrayList ()
List nList = iList
Number n = nList.get (0)
NList.add (0.5); / / Not allowed
We can get Number from the list, because we can assign it to Number regardless of the exact element type of the list (Float, Integer, or Number).
We still can't insert floating-point types into the list. This will fail at compile time because we cannot prove that it is safe. If we want to add a floating-point type to the list, it will break the initial type safety of iList-- it only stores Integer.
Wildcards give us more expressive power than arrays.
Why use wildcards
In the following example, wildcards are used to hide type information from users of API. Internally, Set is stored as CustomerImpl. Users of API only know that they are getting a Set from which they can read Customer.
Wildcards are required here because you cannot assign a value from Set to Set:
Public class CustomerFactory {
Private Set_customers
Public Set getCustomers () {
Return _ customers
}
}
Wildcard and covariant return
Another common use of wildcards is with covariant returns. The same rules as assignment can be applied to covariant returns. If you want to return a more specific generic type in an overridden method, the declared method must use wildcards:
Public interface NumberGenerator {
Public List generate ()
}
Public class FibonacciGenerator extends NumberGenerator {
Public Listgenerate () {
...
}
}
If you want to use an array, the interface can return Number [], while the implementation can return Integer [].
Lower limit
What we're talking about is mainly about upper-limit wildcards. There is also a lower-bound wildcard. List is an unknown list of exact "element types", but it could be Mnumber, or a supertype of Number. So it could be a List or a List.
Lower-bound wildcards are not nearly as common as upper-bound wildcards, but they are necessary when they are needed.
Lower limit and upper limit
List readList = new ArrayList ()
Number n = readList.get (0)
List writeList = new ArrayList ()
WriteList.add (new Integer (5))
The first is a list from which you can read.
The second is a list to which you can write numbers.
Unbounded wildcard
Finally, the content of the List list can be of any type, and it is almost the same as List. You can read the Object at any time, but you cannot write to the list.
Wildcards in public API
In summary, as mentioned earlier, wildcards are important in hiding implementation details from callers, but even if lower-bounded wildcards seem to provide read-only access, they are not because of non-generic methods such as remove (int position). If you want a collection that is truly immutable, you can use methods on java.util.Collection, such as unmodifiableList ().
Remember wildcards when writing API. In general, you should try to use wildcards when passing generic types. It enables more callers to access API.
By receiving List instead of List, the following methods can be called by many different types of lists:
Void removeNegatives (List list)
Construct generic types
Now we will talk about constructing your own generic types. We will show some examples where type safety can be improved by using generics, and we will discuss some common problems when implementing generic types.
Collection style (Collection-like) function
The first example of a generic class is an example of a collection style. Pair has two type parameters, and the field is an instance of the type:
Public final class Pair {
Public final A first
Public final B second
Public Pair (A first, B second) {
This.first = first
This.second = second
}
}
This makes it possible to return two items from a method without having to write a dedicated class for each combination of two types. Another way is to return Object [], which is type-unsafe or untidy.
In the following usage, we return a File and a Boolean from the method. Method can use fields directly without type casting:
Public PairgetFileAndWriteStatus (String path) {
/ / create file and status
Return new Pair (file, status)
}
Pairresult = getFileAndWriteStatus ("...")
File f = result.first
Boolean writeable = result.second
Outside the collection
In the following example, generics are used for additional compile-time security. By parameterizing the DBFactory class to the Peer type you created, you are actually forcing the Factory subclass to return a specific subtype of Peer:
Public abstract class DBFactory {
Protected abstract T createEmptyPeer ()
Public Listget (String constraint) {
Listpeers = new ArrayList ()
/ / database magic
Return peers
}
}
By implementing DBFactory,CustomerFactory, you must return a Customer from createEmptyPeer ():
Public class CustomerFactory extends DBFactory {
Public Customer createEmptyPeer () {
Return new Customer ()
}
}
Generic method
Whether you want to impose constraints on generic types between parameters or between parameters and return types, you can use the generic method:
For example, if you write an inversion function that reverses position, you may not need a generic method. However, if you want to reverse the return of a new List, you may want the element type of the new List to be the same as that of the List passed in. In this case, you need a generic method:
Listreverse (Listlist)
Materialize
When implementing a generic class, you may want to construct an array T []. Because generics are implemented by erasure, this is not allowed.
You can try to cast Object [] to T []. But it's not safe.
Concrete solution
According to the convention of the generics tutorial, the solution uses a "type token", and by adding a Class parameter to the constructor, you can force the client to provide the correct class object for the type parameter of the class:
Public class ArrayExample {
Private Classclazz
Public ArrayExample (Classclazz) {
This.clazz = clazz
}
Public T [] getArray (int size) {
Return (T []) Array.newInstance (clazz, size)
}
}
In order to construct an ArrayExample, the client must pass the String.class to the constructor because the type of String.class is Class.
Owning class objects makes it possible to construct an array with the correct element type.
At this point, I believe you have a deeper understanding of "what's the difference between jdk1.4 and jdk1.5". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.