Java Reflection Best Practices

Java Reflection Best Practices

The examples in this article can be seen and downloaded in the sample code. If you like it, please star it. If you think there are omissions, please submit an issue. If you have a better idea, you can submit a pull request. The sample code in this article is mainly based on jOOR lines. If you want to know more, please check the test code here.

1. Demand

Today a "lazy" programmer suddenly came over and said: "Reflection is so troublesome, I want to make some requirements."

After hearing this, I knew that today would not be easy, as the weird demand came again.

We used to write reflection like this:

  1. public   static <T> T create(HttpRequest httpRequest) {
  2. Object httpRequestEntity = null ;
  3. try {
  4. Class<T> httpRequestEntityCls = (Class<T>) Class.forName(HttpProcessor.PACKAGE_NAME + "." + HttpProcessor.CLASS_NAME);
  5. Constructor con = httpRequestEntityCls.getConstructor(HttpRequest. class );
  6. httpRequestEntity = con.newInstance(httpRequest);
  7. } catch (ClassNotFoundException e) {
  8. e.printStackTrace();
  9. } catch (InstantiationException e) {
  10. e.printStackTrace();
  11. } catch (IllegalAccessException e) {
  12. e.printStackTrace();
  13. } catch (NoSuchMethodException e) {
  14. e.printStackTrace();
  15. } catch (InvocationTargetException e) {
  16. e.printStackTrace();
  17. }
  18. return (T) httpRequestEntity;
  19. }

Because reflection is rarely used in development (for ordinary business development), it is only used when writing some frameworks and annotation frameworks, so I am always unfamiliar with the API. Every time I use the API, I have to check it online, and then I have to experiment by myself, which is very unpleasant. What's worse is that this writing method is very unreadable. I don't want to write reflection like this, I hope reflection can be like

  1. String str = new String();

It's that simple, one line of code and you're done! .

In addition, many people say that reflection affects performance and should be avoided during development. So when should reflection be used and when not? How can reflection be avoided? If you don't understand when to use reflection, it will be difficult to use it flexibly.

2. Analysis

When we received the above requirements, I breathed a sigh of relief because the requirements this time were relatively simple.

I believe some people will say: "Reflection has only a few APIs, and they have never changed. Why don't you check them yourself? If you find it troublesome, don't write code. How can you improve it without knowing the internal details of reflection?"
In fact, it is not the case. Repeatedly writing troublesome code has nothing to do with improving your coding ability. I really don’t know what we have learned after writing thousands of lines of findViewById, except knowing that the class must be bound to the XML file.

So this time we continue to challenge traditional thinking and template code, and see how to write a new generation of reflection code and how to reflect a class with one line of code.
Before we do that, let's take a look at what we generally use reflection for?

  1. Reflection constructs classes that cannot be directly accessed
  2. Set or get to an inaccessible class variable
  3. Calling an inaccessible method

3. Solution

3.1 Write reflection in one line of code

As an Android programmer, let's start with the TextView class. First, define a class variable:

  1. TextView mTv;

Get the instance through reflection:

  1. // With parameters, create a class  
  2. mTv = Reflect.on(TextView. class ).create( this ).get();
  3.  
  4. // Get the class by its full name  
  5. String word = Reflect.on( "java.lang.String" ).create( "Reflect TextView" ).get();
  6.  
  7. // No parameters, create a class  
  8. Fragment fragment = Reflect.on(Fragment. class ).create().get();

Calling methods via reflection:

  1. // Calling a method with no parameters  
  2. Ld( "call getText() : " + Reflect.on(mTv).call( "getText" ).toString());
  3.  
  4. //Calling a method with parameters  
  5. Reflect.on(mTv).call( "setTextColor" , 0xffff0000 );

Get and set class variables through reflection

There is a mText variable in TextView. Let's see how we can approach it.

  1. // Set parameters  
  2. Reflect.on(mTv).set( "mText" , "---------- new Reflect TextView ----------" );
  3.  
  4. // Get parameters  
  5. Ld( "setgetParam is " + Reflect.on(mTv).get( "mText" ));

3.2 When to use reflection and when not to use reflection

It's time to weigh the pros and cons again. First of all, we should make it clear that we should try not to use reflection in daily development, unless we encounter a method that must be called through reflection. For example, I encountered such a situation when I was working on a drop-down notification center function. The system does not provide an API, so we can only call it through reflection, so I wrote a piece of code like this:

  1. <uses-permission android:name= "android.permission.EXPAND_STATUS_BAR" />
  2. private   static   void doInStatusBar(Context mContext, String methodName) {
  3. try {
  4. Object service = mContext.getSystemService( "statusbar" );
  5. Method expand = service.getClass().getMethod(methodName);
  6. expand.invoke(service);
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. }
  10. }
  11.  
  12. /**
  13. * Display the message center
  14. */  
  15. public   static   void openStatusBar(Context mContext) {
  16. // Determine the system version number  
  17. String methodName = (VERSION.SDK_INT <= 16 ) ? "expand" : "expandNotificationsPanel" ;
  18. doInStatusBar(mContext, methodName);
  19. }
  20.  
  21. /**
  22. * Close the message center
  23. */  
  24. public   static   void closeStatusBar(Context mContext) {
  25. // Determine the system version number  
  26. String methodName = (VERSION.SDK_INT <= 16 ) ? "collapse" : "collapsePanels" ;
  27. doInStatusBar(mContext, methodName);
  28. }

Let's first take a look at how concise the doInStatusBar method written using jOOR is:

  1. private   static   void doInStatusBar(Context mContext, String methodName) {
  2. Object service = mContext.getSystemService( "statusbar" );
  3. Reflect.on(service).call(methodName);
  4. }

Wow, just one line of code, pretty cool!

Now that we have the fun, let's look at the reflection problem. Because it is not an API provided by the system, Google uses different method names on different versions to handle it. If we use reflection, we must judge the version, which is something we need to pay attention to. In addition, reflection is really not good in terms of performance, so we need to be cautious here.

My suggestions:

If there are many places in a class that are private, and your needs depend on these methods or variables, then instead of using reflection, it is recommended to copy this class and make it your own class. Classes like toolbar can perform such operations.

When we write our own frameworks, we will definitely use reflection. A simple example is the event bus and annotation framework. Brother Xiang once said: No reflection, no framework. Because it is a self-written framework, the method name and parameters called by reflection generally do not change. Moreover, if you make a runtime annotation framework, reflection will definitely appear. In this case, don't be afraid of reflection, just do it boldly. Because it will allow you to complete many impossible tasks.

To sum up:

When actually doing daily development, try to use reflection as little as possible. You can avoid reflection by copying the original class. When writing a framework, do not avoid reflection and use reflection to help yourself at critical moments.

IV. Postscript

We have finally completed writing reflection with one line of code, avoiding a lot of meaningless template code. It should be noted again that this article is written based on jOOR. Here is the Chinese translation of the original project readme.

jOOR is an open source library that I came across by accident. When I first saw it, I knew it was what I wanted, because at that time I was confused by reflection, and its concise coding method gave me new thinking and greatly improved the readability of the code. By the way, the author is a nice person (he just didn't want me to put a Chinese readme) and his technology is also very good. The project has very detailed test cases and also provides several similar reflection call encapsulation libraries. It can be seen that the author did a lot of research and testing when writing the library, so that we can use the library with confidence (actually there are only two classes).

This article hopes to bring you a new idea of ​​reflection and give you the simplest and most practical way to write reflection, hoping that it can be quickly applied to practice. More importantly, through the analysis of jOOR, I know that I should research similar libraries before writing a library, rather than completely creating a new wheel. Research and testing are important guarantees for code stability.

<<:  Contribution | How to build a team operation system before the product goes online?

>>:  A developer with 11 years of experience talks about how to make an independent game masterpiece

Recommend

Important reminder! Clear immediately when you see it!

"This grass is called ragweed. It is an inva...

If you could take an elevator to space, would you dare to try it?

According to Science and Technology Daily, at the...

Tourism industry advertising unlocks new ways to play with Tik Tok videos!

This article shares with you the May Day holiday ...

Marketing strategy for Labor Day!

The 2021 May Day is approaching. As one of the mo...

Case Review | QQ Browser News New User Retention Growth Methodology

By reviewing a growth case I did last year - the ...

APP promotion: the details of Xiaomi promotion that you don’t know!

After Xiaomi became famous, the term "Weibo ...

iOS 11.3 can fix the frequency reduction problem, but these models do not have

At the end of last year, Apple admitted that it h...

WeChat Mini Program Assistant released: a must-have for developers

Mini programs are free to install and can be used...

How can you become a marketing expert without talent?

When you are engaged in marketing- related work, ...

Small but strong convection, how difficult is it to accurately report it?

Produced by: Science Popularization China Author:...

Play with Zhihu, all the Zhihu operation skills you don’t know are here

Growth is a hot topic . Who doesn’t want targeted...