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

"Academic Education" Baidu bidding replicable optimization methodology

The academic education industry is a relatively s...

Why is it so hard to keep a secret?

"I only told you this, don't tell anyone...

A growth experiment that increased product conversion rate by 30%

The steps for conducting growth experiments are g...

5 ways to promote your app

Now when you open the app store, whether it is fr...

Model S adds a new all-glass transparent sunroof for just 10,000 yuan

Elon Musk seems to be paying special attention to...

A brief discussion on Li Jiaqi’s private domain traffic strategy!

Li Jiaqi may be one of the hottest names in 2019....

Why do clothes that are dried in the shade smell so bad? The reason is...

Audit expert: Zhu Guangsi Member of Beijing Scien...

Fission marketing planning: How to increase the fission factor of products?

However, stimulating users to share can no longer...

How to deal with the situation when there are only a few APP downloads per day

If your app has been launched and follows the fol...

How Momo plays the social networking game—product analysis report!

Purpose of analysis How does Momo do stranger soc...