Reflect java caching, how to do?

Asked

Viewed 98 times

0

If I can instantiate a new object with Reflection, how can I caching for the type it belongs to? newInstance() returns a type Object but I need the primary object, which I can get the guy by name.

But I want to deal with this another way.

Translating. I want to pick through the class name to use the class normally.

Class<?> clazz = Class.forName("br.com.macadu.aprendizado.testando.T3");
Object newInstance = clazz.newInstance();
log.info(newInstance.getClass().toString());
for (Field field : newInstance.getClass().getFields()) {
    log.info(field.toString());
}

How doubt arose about the question. What I want is to instantiate a class via Reflection and return an object of the type that the object is. Not of the Object type as some believed to be.

  • I don’t understand what you mean by "caching for the type that he perceives". You already have the object clazz, and it represents the type. In addition, the method Class.newInstance() was considered deprecated in Java 9. Use clazz.getConstructor().newInstance() in place.

  • Because you do newInstance.getClass() instead of using clazz?

2 answers

1


Maybe what you want is just this:

T3 newInstance = T3.class.getConstructor().newInstance();

In that code, T3.class is an object of the type Class<T3>. From it, you can create instances. This code assumes that T3 has a constructor without parameters.

Let’s assume that T4, on the other hand, has a constructor with a type parameter String. In that case:

T4 newInstance = T4.class.getConstructor(String.class).newInstance("Teste");

The parameters of getConstructor(...) correspond to the types of parameters of the desired constructor, while those of the newInstance(...) are the values themselves.

You can use the Class.forName(String) to get the class by name. But this will give a code like this:

Class<?> clazz = Class.forName("br.com.macadu.aprendizado.testando.T3");
Object instance = clazz.getConstructor().newInstance();

This is particularly useful for you to instantiate classes just by name without knowing exactly what class it is, such as when you have a user-given class name, read from a file, or something like that. But the downside is that like in these cases, the instantiated class can be anything, the only common type you have is Object.

You could even do that:

Class<?> clazz = Class.forName("br.com.macadu.aprendizado.testando.T3");
T3 instance = (T3) clazz.getConstructor().newInstance();

But, that doesn’t make much sense, after all she doesn’t have much advantage over the T3.class.getConstructor().newInstance();.

When you want to instantiate subclasses or implementers of an interface, it gets more interesting:

String implementacao = "com.example.ClasseQueImplementaMinhaInterface";
Class<? extends MinhaInterface> clazz = Class.forName(implementacao)
        .asSubclass(MinhaInterface.class);
MinhaInterface instance = clazz.getConstructor().newInstance();

Use the method newInstance() class Class it might seem like it would be easier, but he was branded as deprecated since Java 9 due to the fact that this method does not behave well in case the constructor throws an exception. In addition, it only works for public builders without parameters.

Finally, if the constructor you want to access is not public, use getDeclaredConstructor(...) instead of getConstructor(...). Also use the setAccessible(true) to ensure access permission even if the class is not public and is in some other package.

String implementacao = "com.example.MaisOutraClasseQueImplementaMinhaInterface";
Class<? extends MinhaInterface> clazz = Class.forName(implementacao)
        .asSubclass(MinhaInterface.class);
Constructor<? extends MinhaInterface> ctor = clazz.getDeclaredConstructor(String.class);
ctor.setAccessible(true);
MinhaInterface instance = ctor.newInstance("Teste");

0

If I understand your question correctly, just do it:

Class<?> clazz = Class.forName("br.com.macadu.aprendizado.testando.T3");
log.info(clazz.toString());
for (Field field : clazz.getFields()) {
    log.info(field.toString());
}

You don’t need to create an instance of the class if the only thing that interests you is the object Class.

In addition, the method newInstance() class Class was marked as deprecated since Java 9 due to the fact that this method does not behave well in case the constructor throws an exception. So instead:

Object newInstance = clazz.newInstance();

Use this:

Object newInstance = clazz.getDeclaredConstructor().newInstance();

Or if you prefer (and make sure the builder is public), use this:

Object newInstance = clazz.getConstructor().newInstance();
  • 1

    I’m not sure I understand his question correctly, but I think he wants to implement a sort of Singleton via Reflection. He wants the first call to create the object, and in the following, that same instance to be returned.

  • @Felipemarine If that’s it, wear one Map<Class<?>, Object> could solve. But, I ended up thinking it best to give a closing vote on the question as "is not clear enough", because really, it’s hard to understand what’s being asked.

  • Now that he edited the question has become clearer. He wants to do the casting of the object, and not the caching.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.