How to write Java code that my colleagues can’t understand?

Original: On the WeChat public码农参上, welcome to share, please keep the source for reprinting.

Hello everyone, I haven’t updated Hydra, but I’m busy with my baby at home.

A few days ago, I happened to catch up with the code review in the group. When I came down in the afternoon, I felt that my blood pressure was full. The variety of codes makes me sigh that the road of code specification is still a long way to go…

So today, I will summarize a wave of code- killing tips in Java. After mastering these tips, you are guaranteed to be able to write code that your colleagues can’t understand~

As for why you have to write code that your colleagues can’t understand, through this lesson, I found that there are still many benefits, just to give a few examples:

  • Colleagues cannot easily modify your code to avoid bugs from improper team collaboration

  • Shaping the irreplaceability of personal ability and avoiding the risk of being fired

  • Helping colleagues treat low blood pressure for many years during code review

Alright, let’s stop the serious nonsense part… Not much nonsense, let’s officially begin. Useless knowledge will increase again…

1. Concealing the sky and crossing the sea

I bet you never imagined that someone would actually poison the comments. Take a look at the code below, it’s as simple as a single line of comment in the main method.

 public static void main(String[] args) {     // \u000d System.out.println("coder Hydra"); }  

Guess how this program works? After execution it actually prints on the console:

 coder Hydra  

Seeing this, are you confused, why is the code in the comment executed?

In fact, the principle lies in the familiar unicode encoding. The above \u000d is a unicode escape character, which represents a newline character. The compiler in java will not only compile the code, but also parse the unicode encoding and replace it with the corresponding characters. So, the above code is actually like this after parsing:

 public static void main(String[] args) {     //     System.out.println("coder Hydra"); }  

In this way, it can explain why the statement in the comment can be executed. Of course, if you feel that the above code is not enough, and you want to be a little more perfect, then you can write the code as follows.

 public static void main(String[] args) {     int a=1;     // \u000d \u0061\u002b\u002b\u003b     System.out.println(a); }  

The execution result will print 2 , for the same reason, because the escaped unicode encoding that follows represents a++; .

As for the benefit of writing it like this, of course, it is used in some places that you don’t want others to understand, to hide people’s eyes and ears. It is estimated that everyone has seen the following joke.

If you write it like this, if the customer understands the code, it will be easy to read it, but if you write it like this, most of you probably think it is a piece of garbled code:

 //\u000d\u0054\u0068\u0072\u0065\u0061\u0064\u002e\u0073\u006c\u0065\u0065\u0070\u0028\u0032\u0030\u0030\u0030\u0029\u003b  

IMHO, without decades of skill, I can’t really see that sleep is implemented here, it’s just perfect.

2. Give up the near and seek the far

To write code that others can’t understand, a very important trick is to complicate simple things . For example, when judging the positive or negative of an int number, it can be written as follows:

 public void judge(int x){     if (x>0){         //...     }else if (x<0){         //...     } }  

But I don’t. I don’t use simple code. I just play. I have to write it as follows:

 public void judge2(int x){     if (x>>>31==0){         //...     }else if (x>>>31==1){         //...     } }  

How, if you write it like this, is it forced to stand up all of a sudden! When others see this, they have to ponder for a while what exactly is written in this piece.

In fact, the principle is also very simple, the >>> used here is an unsigned right shift operation. As a simple example, take -3 as an example, convert it to its complement before shifting:

 111111111111111111111111111111101  

After unsigned right shift by one bit, it becomes the following form, this number is 2147483646 after conversion to decimal.

 011111111111111111111111111111110  

Therefore, when a number of int type is shifted to the right by 31 bits unsigned, all the high bits of the previous 31 bits are 0, and the remaining lowest bit is the original sign bit, so it can be used to judge the positive or negative of the number.

Based on this little knowledge, we can still make a lot of work. For example, instead of a good 0, we can define a 0 in the following way:

 int ZERO=Integer.MAX_VALUE>>31>>1;  

Through the above knowledge, I believe everyone can easily understand, because after shifting a number unsigned to the right by 32 bits, all the bits in the binary are all 0, so 0 will eventually be obtained. So the question is, why don’t I just use Integer.MAX_VALUE>>32 to shift right by 32 bits at a time?

This is because when the int -type number is shifted, the modulo 32 remainder operation will be performed on the parameter on the right side of the operator, so if you write 32 directly, it is equivalent to doing nothing, and the original value is obtained. .

3. Reversing black and white

In ancient times, Zhao Gao referred to a deer as a horse, but today there are code farmers who reverse the truth and falsehood. One of the powerful weapons to prevent a colleague from reading your code is to make him lose his basic judgment ability when he encounters a conditional judgment, and he falls into a fog, not knowing which branch to go next.

The following code, I said it will print fasle , no one will believe it?

 public class TrueTest {     public static void main(String[] args) {         Boolean reality = true;         if(reality) {             System.out.println("true");         } else {             System.out.println("false");         }     } }  

Yes, as long as you know the boolean type, you know that this is not logical, but the following transformation can make it a reality.

First, find a hidden place in the class and insert the following code:

 static {     try {         Field trueField = Boolean.class.getDeclaredField("TRUE");         trueField.setAccessible(true);           Field modifiersField = Field.class.getDeclaredField("modifiers");         modifiersField.setAccessible(true);         modifiersField.setInt(trueField, trueField.getModifiers() & ~Modifier.FINAL);           trueField.set(null, false);     } catch(IllegalAccessException | NoSuchFieldException e) {         e.printStackTrace();     } }  

Then run the above program again, and you will find that false is magically printed.

In fact, the principle is also very simple, first get the TRUE variable defined in the Boolean class through reflection:

 public static final Boolean TRUE = new Boolean(true);  

Then use reflection, remove its final modifier, and finally set its value to false . In the process of using true to define a variable of type Boolean , automatic boxing will be performed, and the following method will be called:

 public static Boolean valueOf(boolean b) {     return (b ? TRUE : FALSE); }  

At this time, b is true , and TRUE is actually false , so the first expression is not satisfied, and it will eventually return false .

In this way, the above printing results can be explained, but remember, when writing this, you must find a hidden corner in the code, and don’t be found, otherwise it will be easy to be beaten badly…

four, to zero

The technique to be introduced next is a bit powerful. It can rewrite the original serial logic into different branches in the judgment logic, and ensure that it can be executed normally in the end.

One question before we start, is there a way to make both if and else statements execute, like in the following example:

 public static void judge(String param){     if (/*judgment condition*/){         System.out.println("step one");     }else {         System.out.println("step two");     } }  

If I say that this method is called only once, the print statements in if and else can be output at the same time, you will definitely say that it is impossible, because this violates the basic common sense of judgment logic in java.

That’s right, no one can do it under the condition that the above modifier can only call the method “once” . But if you move a little bit in the judgment conditions, you can achieve the functions mentioned above. Take a look at the modified code:

 public class IfTest {     public static void main(String[] args) {         judge("Hydra");     }       public static void judge(String param){         if (param==null ||                 new IfTest().equals("Hydra")){             System.out.println("step one");         }else {             System.out.println("step two");         }     } }  

After running, the console prints:

 step one step two  

Surprised or not? In fact, the secret that it can execute is in the judgment condition of if .

When the judge() method is called for the first time, it is not satisfied with the first condition in the NOT-OR operation, so when the second condition is executed, the instantiated initial block code in the anonymous inner class will be executed, and the judge() method will be executed again. When the if condition is satisfied, the first print statement is executed.

The instantiated new object does not meet the conditions in the equals() method, so it does not meet any of the conditions in if , so the statement in else will be executed, and the second print statement will be executed.

In this way, the function of calling the method on the surface and executing the statement block in the if and else is realized at the same time. How about splitting a piece of overall logic into two pieces in this way to confuse your colleagues.

Wu, the bottom of the pot

In the programmer’s world, there has always been a chain of contempt between different languages. For example, those who write c look down on those who write java, because those who directly manipulate memory look very tall, don’t they? So today we pretend to be a c language programmer to operate a piece of memory in java.

Specifically how to do it, or to use the magic class Unsafe in java. Looking at the name, you can also understand that this thing is not very safe if used improperly, so it is more troublesome to obtain the Unsafe instance, and it needs to be obtained through reflection:

 Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); Unsafe unsafe =(Unsafe) unsafeField.get(null);  

After getting this object, we can do whatever we want with the memory. For example, when we implement a simple assignment such as int a=1; we can make it more complicated and make a bend like the following:

 void test(){     long addr = unsafe.allocateMemory(4);     unsafe.putInt(addr,1);     int a=unsafe.getInt(addr);     System.out.println(a);     unsafe.freeMemory(addr); }  

First, apply for 4 bytes of memory space through the allocateMemory method, then write a 1 through the putInt method, and then read a variable of type int length from this address, and finally realize the operation of assigning 1 to a .

Of course, there are many more advanced usages, here are just two examples.

 void test(){     long addr = unsafe.allocateMemory(4);     unsafe.setMemory(addr,4, (byte) 1);     System.out.println(unsafe.getInt(addr));     unsafe.freeMemory(addr); }  

In the above code, 1 of byte type is written to each byte through the setMemory method, and finally the getInt method is called to read 4 bytes at a time as the value of an int variable. The final print result of this code is 16843009 , and the corresponding binary is as follows:

 00000001 00000001 00000001 00000001  

As for memory copying in C language, it is easy to do it with Unsafe :

 void test2(){     long addr = unsafe.allocateMemory(4);     long addr2 = unsafe.reallocateMemory(addr, 4 * 2);       unsafe.putInt(addr, 1);     for (int i = 0; i < 2; i++) {         unsafe.copyMemory(addr,addr2+4*i,4);     }       System.out.println(unsafe.getInt(addr));     System.out.println(unsafe.getLong(addr2));     unsafe.freeMemory(addr);     unsafe.freeMemory(addr2); }  

In the above code, an 8-byte memory space is re-allocated by the reallocateMemory method, and the 4-byte memory space at the beginning of addr is copied into the memory space of addr2 twice. The above code will print:

 1 4294967297  

This is because the binary number stored in the new 8-byte memory space addr2 is as follows, which corresponds to 4294967297 after being converted to the decimal long type.

 100000000000000000000000000000001  

In addition to directly operating memory space, Unsafe also has practical functions such as thread scheduling, object operation, and CAS operation. If you want to know more about it, you can read this Java Double-edged Sword Unsafe Class Detailed Explanation , which opens the door to a new world .

at last

Well, this is the end of the useless knowledge introduction. I believe that after mastering these skills, everyone can bring their own code confusion halo and write different code.

Finally, I suggest that when you write code like this in the project, it may be better to use it with safflower oil and bruises wine.

So, that’s it for this sharing, I’m Hydra, see you in the next article.

The author’s profile,码农参上, a public account that loves to share, interesting, in-depth and direct, chatting with you about technology. Welcome to add friends for further communication.

The text and pictures in this article are from InfoQ

loading.gif

This article is reprinted from https://www.techug.com/post/how-to-write-java-code-that-colleagues-can-t-understand7872239b9abbd184ccab/
This site is for inclusion only, and the copyright belongs to the original author.

Leave a Comment