Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are ten exquisite Java codes

2025-04-07 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of "Ten exquisite Java codes". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

1. Keep in mind the destructor of C++

Remember the destructor of C++? Don't you remember? Then you're really lucky because you don't have to debug code that causes memory leaks because the memory allocated after the object is deleted is not freed. Thank Sun/Oracle for implementing the garbage collection mechanism!

Nonetheless, destructors provide an interesting feature. It understands that memory is released in reverse allocation order. Remember that the same is true in Java, when you manipulate class destructor syntax:

Use JUnit's @ Before and @ After annotations

Allocate, release JDBC resources

Call the super method

There are various other use cases. Here is a concrete example of how to implement the SPI of some event listeners:

@ Override

Public void beforeEvent (EventContext e) {

Super.beforeEvent (e)

/ / Super code before my code

}

@ Override

Public void afterEvent (EventContext e) {

/ / Super code after my code

Super.afterEvent (e)

}

The infamous philosopher dining problem is another good example of why it is important. For questions about the dining of philosophers, please see the link:

Http://adit.io/posts/2013-05-11-The-Dining-Philosophers-Problem-With-Ron-Swanson.html

Rule: whenever you use before/after, allocate/free, and take/return semantics to implement logic, consider whether to perform after/free/return operations in reverse order.

two。 Don't trust your early SPI evolution judgment.

Providing customers with SPI makes it easy for them to inject custom behavior into your library / code. Be careful that your SPI evolution judgment may confuse you into thinking that you (don't) intend to need additional parameters. Of course, features should not be added prematurely. But once you release your SPI, once you decide to follow semantic versioning, when you realize that you may need another parameter in some case, you will really regret adding a stupid single parameter to SPI:

Interface EventListener {

/ / Bad

Void message (String message)

}

What if you also need a message ID and source? The API evolution will prevent you from adding parameters to the above types. Of course, with Java8, you can add a defender method to "defend" against your early bad design decisions:

Interface EventListener {

/ / Bad

Default void message (String message) {

Message (message, null, null)

}

/ / Better?

Void message (

String message

Integer id

MessageSource source

);

}

Note that, unfortunately, the defender method cannot use the final modifier.

But it's much better to use context objects (or parameter objects) than to pollute your SPI in many ways.

Interface MessageContext {

String message ()

Integer id ()

MessageSource source ()

}

Interface EventListener {

/ / Awesome!

Void message (MessageContext context)

}

You can evolve MessageContext API more easily than EventListner SPI, because few users will implement it.

Rule: whenever you specify a SPI, consider using context / parameter objects instead of writing methods with fixed parameters.

Note: it is also a good idea to exchange results through a dedicated MessageResult type, which can be constructed using the builder API. This will greatly increase the flexibility of SPI evolution.

3. Avoid returning anonymous, local or inner classes

Swing programmers often generate hundreds of anonymous classes with just a few keyboard shortcuts. In most cases, this is fine as long as you follow the interface and do not violate the SPI subtype lifecycle of the SPI subtype. But don't use anonymous, local, or inner classes frequently for a simple reason-they save references to external classes. Because wherever they go, external classes have to follow. For example, if you operate improperly outside the domain of a local class, the entire object graph will change subtly, which may cause memory leaks.

Rule: before writing an anonymous, local, or inner class, think twice about whether you can convert it to a static or normal * class, so as to avoid methods returning their objects to the outer domain.

Note: use double curly braces to initialize simple objects:

New HashMap () {{

Put ("1", "a")

Put ("2", "b")

}}

This method uses the instance initialization method (initializer) described in the JLS §8.6 specification. It looks good on the surface, but in fact it is not advocated. Because if you use completely separate HashMap objects, the instance will not always hold references to external objects. In addition, this allows the class loader to manage more classes.

4. Start writing SAM now!

Java8 is getting closer. Along with Java8 comes lambda expressions, whether you like it or not. Although your API users may like it, you make sure they can be used as often as possible. So unless your API accepts simple "scalar" types, such as int, long, String, and Date, let your API receive SAM as often as possible.

What is SAM? SAM is a single abstract method [type]. Also known as a function interface, it will soon be annotated as @ FunctionalInterface. This fits well with Rule 2, where an EventListener is actually a SAM. The SAM of * * has only one parameter, as this will further simplify the writing of lambda expressions. Conceive and write

Listeners.add (c-> System.out.println (c.message ()

To replace

Listeners.add (new EventListener () {

@ Override

Public void message (MessageContext c) {

System.out.println (c.message ())

}

});

Imagine dealing with XML in a JOOX way. JOOX contains a lot of SAM:

$(document)

/ / Find elements with an ID

.find (c-> $(c) .id ()! = null)

/ / Find their child elements

.children (c-> $(c) .tag () .equals ("order"))

/ / Print all matches

.each (c-> System.out.println ($(c)

Rule: be nice to your API users and write SAM/ function interfaces from now on.

Note: there are many interesting blogs about Java8 lambda expressions and improved Collections API:

Http://blog.informatech.cr/2013/04/10/java-optional-objects/

Http://blog.informatech.cr/2013/03/25/java-streams-api-preview/

Http://blog.informatech.cr/2013/03/24/java-streams-preview-vs-net-linq/

Http://blog.informatech.cr/2013/03/11/java-infinite-streams/

5. Avoid letting the method return null

I have written one or two articles about java NULLs and explained the introduction of new Optional classes in Java8. From an academic or practical point of view, these topics are quite interesting.

Although Null and NullPointerException are still hard wounds to Java at this stage, you can still design API without any problems. When designing an API, you should avoid letting the method return null as much as possible, because your users may call the method chained:

Initialise (someArgument) .cake (data) .dispatch ()

As you can see from the code above, none of the methods should return null. In fact, using null would be considered quite unusual under normal circumstances. Libraries like jQuery or jOOX have completely abandoned null on iterable objects.

Null is commonly used in deferred initialization. In many cases, delayed initialization should also be avoided without seriously affecting performance. In fact, if the data structure involved is too large, use deferred initialization with caution.

Rule: methods should avoid returning null at any time. Null is only used to represent the semantics of "uninitialized" or "non-existent".

6. Never return an empty (null) array or List when designing an API

Although in some cases it is possible for a method to return a value of null, never return an empty array or empty collection! Take a look at the java.io.File.list () method, which is designed as follows:

This method returns a string array of all files or directories under the specified directory. If the directory is empty, then the returned array is also empty. Returns null if the specified path does not exist or an Icano error occurs.

Therefore, this method is usually used like this:

File directory = / /...

If (directory.isDirectory ()) {

String [] list = directory.list ()

If (list! = null) {

For (String file: list) {

/ /...

}

}

}

Do you think it is necessary to check null? Most IPUBO operations result in IOExceptions, but this method only returns null. Null is unable to store iCompO error messages. Therefore, such a design has the following three deficiencies:

Null does not help to find errors

Null can't indicate that the iCandle O error is caused by the incorrect path corresponding to the File instance.

Everyone may forget to judge the null situation.

If you look at the problem in terms of collective thinking, then an empty (empty) array or collection is an implementation of "non-existence". Returning an null array or collection makes almost no practical sense, except for delayed initialization.

Rule: the returned array or collection should not be null.

7. Avoid states and use functions

The advantage of HTTP is statelessness. All relevant states are transferred in each request and response. This is the essence of REST naming: including state transfer (Representational state transfer). It's also great to do this in Java. Think about this from the perspective of rule 2 when the method receives the state parameter object. If the state is transferred through this object instead of manipulating the state from the outside, things will be easier. Take JDBC as an example. The following example reads a cursor from a stored program.

CallableStatement s =

Connection.prepareCall ("{? =.}")

/ / Verbose manipulation of statement state:

S.registerOutParameter (1, cursor)

S.setString (2, "abc")

S.execute ()

ResultSet rs = s.getObject (1)

/ / Verbose manipulation of result set state:

Rs.next ()

Rs.next ()

This makes JDBC API so weird. Every object is stateful and difficult to manipulate. Specifically, there are two main problems:

It is difficult to properly handle stateful API in a multithreaded environment

It is difficult to make stateful resources available globally because the state is not described

Rules: more functional style implementation. Transfer the state through the method parameters. Rarely manipulate the object state.

8. Short-circuit equals ()

This is a relatively easy method to operate. In a more complex object system, you can get a significant performance improvement, as long as you first make an equality judgment in the equals () method of all objects:

@ Override

Public boolean equals (Object other) {

If (this = = other) return true

/ / other equality judgment logic.

}

Note that other short-circuit checks may involve null value checking, so you should also add:

@ Override

Public boolean equals (Object other) {

If (this = = other) return true

If (other = = null) return false

/ / Rest of equality logic...

}

Rule: use short circuits in all your equals () methods to improve performance.

9. Try to make the method final by default.

Some people may disagree with this because it is against the habit of Java developers to make the method final by default. But if you have complete control over the code, it is certainly true that the method defaults to final:

If you really need to overwrite (override) a method (do you really need it? ), you can still remove the final keyword

You will never accidentally override any method

This is especially true for static methods, where "coverage" (actually masking) works little. I recently came across a bad example of masking static methods in Apache Tika. Take a look:

TaggedInputStream.get (InputStream)

TikaInputStream.get (InputStream)

TikaInputStream extends TaggedInputStream to obscure its static get () method with a relatively different implementation.

Unlike conventional methods, static methods cannot override each other because the place of call is bound to static method calls at compile time. If you are unlucky, you may accidentally get the wrong method.

Rule: if you have complete control over your API, make as many methods as possible default to final.

10. Avoidance method (T …) Signature

In special cases, use the "accept-all" variable parameter method to receive an Object. There is nothing wrong with the parameter:

Void acceptAll (Object... All)

Writing such an approach gives the Java ecosystem a bit of a JavaScript feel. Of course, you may want to limit the actual types according to the real situation, such as String. Because you don't want to be too restrictive, you might think it's a good idea to replace Object with generic T:

Void acceptAll (T... All)

But it's not. T is always inferred as Object. In fact, you may just think that generics cannot be used in the above methods. More importantly, you may think you can overload the above methods, but you can't:

Void acceptAll (T... All)

Void acceptAll (String message, T... All)

It looks as if you can optionally pass a String message to the method. But what happens to this call?

AcceptAll ("Message", 123, "abc")

The compiler deduces T as >, which will make the call ambiguous!

So whenever you have a "accept-all" signature (even if it's generic), you'll never be able to type-safe overload it. API users may only let the compiler "accidentally" choose the "right" method when they are lucky. But it is also possible to use the accept-all method or no method can be called.

Rule: avoid "accept-all" signatures if possible. If not, do not overload such a method.

This is the end of the content of "what are the Ten wonderful Java codes". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report