Construct inner class objects through reflection
First, write a class containing the inner class under the javalang package:
package javalang; public class Outer { public static class Inner1{} }
Note that this class is public static, and we will slowly remove these modifiers later.
To create an Inner1 object through reflection, you must first obtain the Class object of Inner1. We write the main method in Outer:
public class Outer { public static class Inner1{} public static void main(String[] args) { (); } }
Output result:
class $Inner1
Then let's try this class name right:
public static void main(String[] args) throws Exception { (("$Inner1")); }
Run it, that's right. Then use it to create objects. Creating objects depends on the constructor method. Is there a constructor method for this class? We can write this:
public static void main(String[] args) throws Exception { (("$Inner1").getConstructors().length); }
Run it and output 1. It seems there is. Then see what this constructor looks like:
public static void main(String[] args) throws Exception { (("$Inner1").getConstructors()[0]); }
Output result: public $Inner1(). This is the default construction method. So we can write this:
public static void main(String[] args) throws Exception { (("$Inner1") .getConstructors()[0].newInstance(); }
Output result: $Inner1@ca0b6. This means that the execution has been successful.
Next, we remove the Inner public keyword and run it again. The result is an error:
Exception in thread "main" : 0
This means that no constructor was found. Really not? Let's change the main method back:
public static void main(String[] args) throws Exception { (("$Inner1") .getConstructors().length); }
Output result: 0. Is there really no constructor? Actually, it's not, it's just that the construction method is not public. At this time, we must use getDeclaredConstructors() to obtain:
public static void main(String[] args) throws Exception { (("$Inner1") .getDeclaredConstructors().length); }
Output result: 1. This finds the construction method. Then we continue to call this constructor:
public static void main(String[] args) throws Exception { (("$Inner1") .getDeclaredConstructors()[0].newInstance()); }
Output result: $Inner1@ca0b6. Now we can use reflection to construct objects of non-public inner classes.
Next, we will remove the static keyword. An error was reported at this time:
Exception in thread "main" : wrong number of arguments
What does this mean? When we call, we did not pass parameters, and the error content means that the number of parameters is incorrect. So what parameters do this constructor have? Let's change the code and see:
public static void main(String[] args) throws Exception { (("$Inner1") .getDeclaredConstructors()[0]); }
Output result: $Inner1()
It turns out that the constructor requires an Outer type parameter. This is easy to do:
public static void main(String[] args) throws Exception { (("$Inner1") .getDeclaredConstructors()[0].newInstance(new Outer())); }
Output result:
$Inner1@ca0b6
OK, so that's it. It seems that non-static inner classes do not have a default construction method, and an instance of the outer class needs to be passed as a parameter during construction.
Java: How to access an object
A headache for Java beginners is how to decide whether to define an object as a method variable or a member variable?
Beginners won't care about this at the beginning. But as the program written becomes larger and more large and more categories, this kind of distress also arises.
But what I want to write here is: How to arrange an object as you wish so that you can access it at any time. With this in mind, you can freely decide where to place an object.
Here is a simple example:
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); } // Get the time after the date object is one hour private static void anHourLater() { // How to get the date variable in the main() method here? } }
As described in the anHourLater() method, you want to get the time after date one hour. What to do? There are several methods below.
(1) Parameters pass
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); anHourLater(date); } // Get the time after the date object is one hour private static void anHourLater(Date d) { Date anHourLater = new Date(() + 3600000); } }
(2) Defined as a member. Members can be accessed by all methods, and the initialization of members can be placed in a defined place or in any method.
public class AccessingObject { private static Date date; public static void main(String[] args) { date = new Date(); anHourLater(); } // Get the time after the date object is one hour private static void anHourLater() { Date anHourLater = new Date(() + 3600000); } }
(3) Put it in another category. In the following example, it can be accessed by all classes in the same package, not limited to the AccessingObject class.
public class AccessingObject { public static void main(String[] args) { = new Date(); } // Get the time after the date object is one hour private static void anHourLater() { Date anHourLater = new Date(() + 3600000); } } class DateHolder { public static Date date; }
Compared with these three examples, the first two can only be used internally in the class, which is relatively safe. If you don't want this object to be directly modified by other classes, don't use the third method.
The difference between the first and second methods is that if an object is only used in the method, then when the method is executed, the object can be easily recycled (note that it is not recycled immediately). If defined as a member of a class, the object will be recycled only after the class it is recycled. Obviously, the first method is the most resource-saving, and we should try our best to use the first method.
Looking back at these three examples, if the main() method wants to obtain the one-hour time obtained in the anHourLater() method, it also has several corresponding ways. There is no need to change the last two examples, the date object can be accessed directly; the first example has two ways to modify it:
(1) as return value
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); Date anHourLater = anHourLater(date); } // Get the time after the date object is one hour private static Date anHourLater(Date d) { return new Date(() + 3600000); } }
(2) Directly modify the content of the parameters
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); anHourLater(date); } // Get the time after the date object is one hour private static void anHourLater(Date d) { (() + 3600000); } }
The second method should be used with caution, because it is wrong to touch others. You don’t know if the caller of the method likes you to do this.