The * Effective Java Third Edition * I ordered has finally arrived, so I have summarized the changes from the second edition. I have skipped the personal notes and the parts that are not different from the second edition, so please forgive me for any omissions. Since the second edition refers to the Japanese version, there may be inconsistencies in relation to the translated text. I would be grateful if you could point out any mistakes.
Quotation from Effective Java Third Edition or its translation
Plaintext-Personal impressions
Item 2
The builder has been added with recursive parameters.
You can fluently design subclasses by setting the builder returned by the parent abstract class Pizza
toBuilder <T extends Builder <T >>
and the type returned by its method ʻaddTopping () to
T`. ..
** Static utility classes and singletons are not suitable for classes whose behavior can be parameterized by resources **
Supplier <T>
rather than pass Factory.Item 6
The example of creating unnecessary objects has been changed from using Calendar
toString.matches ()
(the problem is that it creates Pattern
each time).
The cleaners added in Java 9 have been talked about.
** Cleaners aren't as dangerous as finalizers, but they're still unpredictable, slow, and generally unnecessary **
finalizer attack --Use the finalizer to leave the bad object in the heap and call the method (the description itself was in the 2nd edition, but it is more emphasized)
Should implement ʻAutoCloseable` instead
Item 10
Personally, I don't like AutoValue very much, so I use Lombok or write it in Kotlin.
IDEs do not make careless mistakes, and humans do
IDEs don't make inadvertent mistakes, but humans do
Item 11
The code example has been modified to use Type.hashCode ()
(Short.hashCode ()
, etc.) to generate the hash code.
The documentation for hashCode generation has become more pronounced from "don't do it" to "don't do it" (documentation makes it impossible to change in the future).
Item 12
toString ()
in static utility classes or enumeratorsItem 13
Cloneable
(can be shared without copying in the first place)Item 14
Type.compare ()
Comparator.comparing ... ()
Item 15
Item 19
@implSpec
Item 20
** It is not always possible to write a default method without changing all possible implementations ** ** It is still of utmost importance that great care must be taken when designing an interface **
synchronizedCollection
The default method is not synchronized (until it is overridden)!Deleted, merged with Item 42
Item 24
You can write multiple public classes in a language like Kotlin, but I think it's better to separate them as much as possible for readability.
"With new code" is gone (not forcibly refactored)
Item 27:
Description of diamond operator
Item 30
With the addition of the diamond operator, the description of the newHashMap
utility method for omitting type parameters has disappeared when creating a new collection.
generic singleton pattern
private static UnaryOperator<Object> IDENTITY_FN = (t) -> t;
@SuppressWarnings("unchecked")
public static <T> UnaryOperator<T> identityFunction() {
return (UnaryOperator<T>) IDENTITY_FN;
}
I don't think I have many opportunities to use it in actual battles.
@SafeVarargs
and stop if it's not safeItem 34
Convert from String to Enum
private static final Map<String, Operation> stringToEnum = Stream.of(values()).collect(toMap(Object::toString, e -> e));
public static Optional<Operation> fromString(String symbol) {
return Optional.ofNufllable(stringToEnum.get(symbol));
}
I personally want to throw an exception (discussed in Item 55).
The Payroll Day
was subtly refactored.
Item 37
Why did you change Herb to Plant and Type to Lifecycle?
Item 39
JUnit -> JUnit 3 JUnit 4 is annotation-based, so I'm just following the advice in this section.
Lambda parameter types are not used unless it makes the program cleaner. Lambda lacks name and documentation. Do not use lambdas if the process is not self-explanatory or is larger than a few lines.
Function :: identity
vs x-> x
)The "template method" pattern, in which subclasses override "primitive methods" to customize the behavior of superclasses, is much less attractive. A modern alternative is to provide a static factory or constructor that accepts function objects that do the same thing.
Use the standard one rather than creating your own functional interface
When defining your own functional interface
Widely used and benefiting from descriptive names
If you have a strongly related contract
If you benefit from your own default method
Use @FunctionalInterface
Do not create different overloaded methods with different functional interfaces in the same position as arguments if they can be ambiguous to the client.
is difficult to understand because it takes
Runnableand
Callable just because you can doesn't mean you should
** Overuse of streams makes the program hard to read and maintain **
My ears hurt
** Using helper methods in code that uses stream pipelines is even more important than using them in code that uses iterators. ** **
char
The method name (
primes
) is a plural noun that describes the elements of the stream. This naming convention is highly recommended for all methods that return a stream because it improves the readability of the stream pipeline.
The
forEach
instruction should only be used to report the processing results of a stream, not to do any processing.
It's easy to say forEach (e-> list.add (e))
.
If you are writing a public API that returns a sequence, you should write it not only for those who want to write a stream pipeline, but also for those who want to write a for-each statement.
** Do not store large sequences in memory just to return them as a collection. ** **
Consider implementing a collection for a special purpose.
** If the source is
Stream.iterate
or the intermediate operationlimit
is used, paralleling the pipeline will not improve performance. ** **
** Parallelizing streams of ʻArrayList
,
HashMap,
HashSet,
ConcurrentHashMapinstances, arrays, ʻint
range, andlong
range is the biggest performance gain. Let's do it. ** **
Parallelizing streams not only slows performance, but can also lead to incorrect results and unpredictable behavior.
Difference between forEach
and forEachOrdered
Rough guide: Performance may improve if stream elements x code lines> 100,000
is exceeded
Source in the book: When to use parallel streams
It is important to remember that stream parallelization is a performance optimization. As with any optimization, you should measure performance before and after the change to make sure you need to do so.
Item 49
Item 50
**
Date
is obsolete and should no longer be used in new code **
** Container-types and options such as maps, streams and arrays must not be optionally wrapped. Declare a method to return ʻOptional
` if it may not return a result, * and *, and the client needs to do something special. ** **
Use ʻOptionalInt, ʻOptionalLong
, ʻOptionalDouble. If ʻOptional <T>
, auto boxing will occur and performance will deteriorate.
Do not use options for collection or array keys, values, or elements
Saving options in fields is often a "smell" code, but it can also be justified (for example, if you have a lot of optional fields and you just need to return the optional from the getter).
Item 56
@implSpec
Item 59
ThreadLocalRandom
rather than Random
Delete
Item 75
as an argument has been added to ʻIndexOutOfBoundsException
.The stream has been added as a candidate.
The danger of serialization is heavily emphasized.
** The best way to avoid serialization vulnerabilities is to not deserialize anything ** ** There is no reason to use Java serialization on newly written systems **
The next best thing is to ** never deserialize untrusted data **
java.io.ObjectInputFilter
In conclusion, serialization is dangerous and should not be used.
Old | new |
---|---|
AMD Opteron 170 | Core i7-4770K |
2GB RAM | DDR3-1866 16GB RAM |
Windows XP | Windows 7 Professional SP1 |
JDK 1.6 Java HotSpot | Azul Zulu 9.0.0.15 |
Recommended Posts