10 Practical but Paranoid Java Programming Techniques

10 Practical but Paranoid Java Programming Techniques

[[147453]]

After you've been coding for a while (I've been programming for about 20 years now), you start to get used to it. Because, you know...

Anything can go wrong, yes, it does.

That's why we need to adopt "defensive programming", that is, some paranoid habits. Here are my 10 most useful but paranoid Java programming techniques. Let's take a look:

1. Put the String string first

In order to prevent occasional NullPointerException exceptions, we usually place String on the left side of the equals() function to implement string comparison, as shown in the following code:

  1. // Bad  
  2. if (variable.equals( "literal" )) { ... }
  3. //Good  
  4. if ( "literal" .equals(variable)) { ... }

This is something you can do with your head, rewriting the expression from the Bad version of the code to the Good version of the code, and nothing is lost in the process. Different opinions are welcome...

2. Don’t trust early JDK APIs

In the early days of Java, programming was a painful thing. The APIs were still very immature, and perhaps you have come across the following code block:

  1. String[] files = file.list();
  2. // Watch out  
  3. if (files != null ) {
  4. for ( int i = 0 ; i < files.length; i++) {
  5. ...
  6. }
  7. }

Seems paranoid? Maybe, but look at the Javadoc:

If this virtual path does not represent a folder directory, this method returns null. Otherwise, it returns an array of strings, each string representing a file or folder in the directory.

Yes, that's right. We can add some validation:

  1. if (file.isDirectory()) {
  2. String[] files = file.list();
  3. // Watch out  
  4. if (files != null ) {
  5. for ( int i = 0 ; i < files.length; i++) {
  6. ...
  7. }
  8. }
  9. }

3. Don’t trust “-1”

I know this is paranoid, but the Javadoc for the String.indexOf() method clearly states: The index of the first occurrence of the specified character in the object. If it is -1, it means that the character is not in the character sequence.

So it is natural to use -1, right? I say not, please look at the following code:

  1. // Bad  
  2. if (string.indexOf(character) != - 1 ) { ... }
  3. //Good  
  4. if (string.indexOf(character) >= 0 ) { ... }

Who knows. Maybe by then they've changed the encoding to be case insensitive, and maybe returning -2 would be a better approach? Who knows.

4. Avoid accidental assignments

Yes. This probably happens quite often.

  1. // Ooops  
  2. if (variable = 5 ) { ... }
  3. // Better (because causes an error)  
  4. if ( 5 = variable) { ... }
  5. // Intent (remember. Paranoid JavaScript: ===)  
  6. if ( 5 === variable) { ... }

So you can put the comparison constant on the left side, so that no accidental assignment errors will occur.

5. Check Null and Length

Regardless, whenever you have a collection, array, etc., make sure it exists and is not empty.

  1. // Bad  
  2. if (array.length > 0 ) { ... }
  3. //Good  
  4. if (array != null && array.length > 0 ) { ... }

You don't know where these arrays come from, maybe from an earlier version of the JDK API, who knows.

6. All methods are final

You may tell me your open/closed principle, but it's all bullshit. I don't trust you (correctly inheriting all subclasses of my parent class), and I don't trust myself (accidentally inheriting all subclasses of my parent class). So strictly use final for methods that have clear meanings.

  1. // Bad  
  2. public   void boom() { ... }
  3. // Good. Don't touch.  
  4. public   final   void dontTouch() { ... }

7. All variables and parameters are final

Like I said. I don't trust myself (not to accidentally overwrite my values). That being said, I don't trust myself because...

…which is why all variables and parameters are final.

  1. // Bad  
  2. void input(String importantMessage) {
  3. String answer = "..." ;
  4. answer = importantMessage = "LOL accident" ;
  5. }
  6. //Good  
  7. final   void input( final String importantMessage) {
  8. final String answer = "..." ;
  9. }

8. Don’t trust generics when overloading

Yes, it can happen. You believe you wrote this super nice API and it's intuitive, and along comes some user who just casts primitives to Object until the damn compiler stops whining, and suddenly they're linking against the wrong method, thinking it's your fault.

Look at the following code:

  1. // Bad  
  2. <T> void bad(T value) {
  3. bad(Collections.singletonList(value));
  4. }
  5. <T> void bad(List<T> values) {
  6. ...
  7. }
  8. //Good  
  9. final <T> void good( final T value) {
  10. if (value instanceof List)
  11. good((List<?>) value);
  12. else  
  13. good(Collections.singletonList(value));
  14. }
  15. final <T> void good( final List<T> values) {
  16. ...
  17. }

Because, you know... your users, they're like

  1. // This library sucks  
  2. @SuppressWarnings ( "all" )
  3. Object t = (Object) (List) Arrays.asList( "abc" );
  4. bad(t);

Trust me. I've seen it all. Including the following

This kind of paranoia is still good.

9. Always throw exceptions in the Default of the Switch statement

Switch statement… one of those ridiculous statements I don’t know whether to stand in awe or cry over, but anyway, since we insist on using switch, we might as well use it the best way possible. Take a look at the following code:

  1. // Bad  
  2. switch (value) {
  3. case   1 : foo(); break ;
  4. case   2 : bar(); break ;
  5. }
  6. //Good  
  7. switch (value) {
  8. case   1 : foo(); break ;
  9. case   2 : bar(); break ;
  10. default :
  11. throw   new ThreadDeath( "That'll teach them" );
  12. }

When value == 3, a prompt will appear saying that the file cannot be found, instead of confusing people.

10.Switch statement with curly braces

In fact, switch is the most evil statement, like some people who are drunk or lost in gambling wrote the code, see the following example:

  1. // Bad, doesn't compile  
  2. switch (value) {
  3. case   1 : int j = 1 ; break ;
  4. case   2 : int j = 2 ; break ;
  5. }
  6. //Good  
  7. switch (value) {
  8. case   1 : {
  9. final   int j = 1 ;
  10. break ;
  11. }
  12. case   2 : {
  13. final   int j = 2 ;
  14. break ;
  15. }
  16. // Remember:  
  17. default :
  18. throw   new ThreadDeath( "That'll teach them" );
  19. }

In a switch statement, each case statement has a scope of only one line of statements. In fact, these case statements are not even real statements. They are like jump labels in a goto statement.

in conclusion

Paranoid programming may seem weird sometimes, because the code often turns out to be a little more verbose than what is needed. You might think, "Oh, that will never happen", but like I said. After 20 years or so of programming, you don't want to just fix these stupid bugs because the programming language is so old and flawed. Because you know...

Now it’s your turn! What’s your most obsessive programming quirk?

<<:  A Preliminary Study on CoordinatorLayout and Behaviors in Android Support Design

>>:  Internet people love to slap people in the face? The laid-off employees can fill up a "one acre of land"

Recommend

If air enters the blood vessels during infusion, is there any hope?

Image source: Qiantu.com If air enters the blood ...

Enterprise Weibo operation methods and strategies!

When it comes to corporate Weibo operations , aft...

Advertising creativity is highly homogenized. How can we break the deadlock?

What should we do if our creative ideas become ho...

Analysis of 7 bidding methods for Baidu search OCPC

Baidu search ocpc bidding is the current mainstre...

Scientists have discovered a magical molecule. Is there a cure for baldness?

Recently, many media reported that Chinese and Am...

Using macaca for mobile hybrid automation testing (Part 2)

Macaca macaca is an open-source automated testing...

Information flow advertising: budget 400, keywords 2W+, how to promote?

This week, the editor has sorted out several diff...

Why does Microsoft prefer mobile keyboard apps recently?

[[163288]] Recently, Microsoft quietly launched a...

Don’t know how to design buttons? Just master these 5 golden rules

Hello everyone, this is TCC Translation Intellige...