Creating a class and creating an instance from a string - java

I have a problem in creating an object.
Basically I would like to create an object from a given class by taking originally a string. I know that using Class.forName(field) works, but not in my case and I will show you why below. I have thought about reflection but fear it will cause the same problem.
My code as of right now is (template is a String):
int n = template.length();
String field = at.getFieldName().trim();
field = field.substring(0, field.length() - 1);
Class<?> correctClass = Class.forName(field);
UniqueEntity<correctClass> ue = new UniqueEntity<correctClass>();
The error message I get is that correctClass cannot be resolved to a type.

Once you used Class.forName() method you got your Class instance (variable correctClass) invoke method getConstructor() or getConstructors() to get an instance of class Constructor. Once you get your instance of class Constructor invoke method newInstance() to get an instance of your class. Here is the example:
Class myClass = Class.forName(field);
Constructor constructor = myClass.getConstructor()
Object o = constructor.newInstance()
All this assuming that your class has default constructor.

In order for you to be able to create a UniqueEntity with the type of your reflective class, you need to pass the class type into a generic helper method.
private static <T> UniqueEntity<T> createEntity(Class<T> clazz) {
return new UniqueEntity<T>(clazz);
}
Code
import java.lang.reflect.Type;
public class Generic {
public static void main(String[] args) {
try {
String field = "java.lang.Integer";
UniqueEntity<?> entity = fromField(field);
System.out.println(entity);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static UniqueEntity<?> fromField(String field) throws ClassNotFoundException {
return createEntity(Class.forName(field));
}
private static <T> UniqueEntity<T> createEntity(Class<T> clazz) {
return new UniqueEntity<T>(clazz);
}
private static class UniqueEntity<T> {
private final Type type;
public UniqueEntity(Class<T> clazz) {
this.type = clazz.getGenericSuperclass();
}
#Override
public String toString() {
return "UniqueEntity [type=" + type + "]";
}
}
}

Related

Unable to instantiate an object using parameterized Constructor in java

This is the class I want to Instantiate:
public class GoogleSheetsAPI {
String spreadsheetId;
Sheets service;
String credentialsFile;
public void GoogleSheetsAPI() {
}
public void GoogleSheetsAPI(String spreadsheetId, String credentialsFile) throws Exception {
this.spreadsheetId = spreadsheetId;
this.credentialsFile = credentialsFile;
service = getSheetsService();
}
}
This is how I am creating an object of class GoogleSheetsAPI
GoogleSheetsAPI googleSheetsAPI = new GoogleSheetsAPI(spreadsheetId, credentiialsFile);
The constructor must not have void, it should be:
public GoogleSheetsAPI(String spreadsheetId, String credentialsFile) throws Exception {
this.spreadsheetId = spreadsheetId;
this.credentialsFile = credentialsFile;
service = getSheetsService();
}
the constructor does not have any return type... because is a special method, if you define own constructor then not define empty constructor because jvm provide default...
Class.newInstance invokes the no-arg constructor
Class<?> cl = Class.forName("javax.swing.JLabel");
Constructor<?> cons = cl.getConstructor(String.class);
Object o = cons.newInstance("JLabel");
to invoke a different constructor, you need to use the reflection package (java.lang.reflect).

getConstructor with no parameters

I can't seem to use getConstructor for constructors with no parameters.
I keep getting the following exception:
java.lang.NoSuchMethodException: classname.<init>()
Here is the code:
interface InfoInterface {
String getClassName();
String getMethodName();
String getArgument();
}
class asa implements InfoInterface {
#Override
public String getClassName() {
return ("jeden");
}
#Override
public String getMethodName() {
return ("metoda");
}
#Override
public String getArgument() {
return ("krzyk");
}
}
class Jeden {
Jeden() {
System.out.println("konstruktor");
}
public void Metoda(String s) {
System.out.println(s);
}
}
class Start {
public static void main(String[] argv) {
if (argv.length == 0) {
System.err.println("Uzycie programu: java Start nazwa_klasy nazwa_klasy2...");
return;
}
try {
for (int x = 0; x < argv.length; x++) {
Class<?> c = Class.forName(argv[x]);
InfoInterface d = (InfoInterface) c.newInstance();
String klasa = d.getClassName();
String metoda = d.getMethodName();
String argument = d.getArgument();
Class<?> o = Class.forName(klasa);
// o.newInstance();
Constructor<?> oCon = o.getConstructor();
System.out.println("ASD");
Class<?> p = (Class<?>) oCon.newInstance();
}
} catch (Exception e) {
System.out.println(e);
}
}
}
o.newInstance(); prints "konstruktor" without problems.
The problem is clear when you read the javadoc of .getConstructor():
Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.
Emphasis mine.
In your code, the constructor is not public!
Example:
// Note: class is NOT public -- its default constructor won't be either
final class Test
{
public static void main(final String... args)
throws NoSuchMethodException
{
// throws NoSuchMethodException
Test.class.getConstructor();
}
}
Obligatory link to an SO answer which also gives the JLS reference. In particular, note that the default constructor has the same access modifier as the class.
It seems as if your class provides a constructor that is NOT a default constructor. The call to getConstructor() without parameters requires the class to have a default constructor. The following test illustrates this.
import org.junit.Test;
public class ConstructorTest {
public static class ClassWithParameterizedConstructor {
public ClassWithParameterizedConstructor(final String param) {
// A parameterized constructor, no default constructor exists
}
}
#Test
public void testFoo() throws NoSuchMethodException {
// Parameterized constructor lookup works fine
ClassWithParameterizedConstructor.class.getConstructor(String.class);
// This doesn't work since there is no default constructor
ClassWithParameterizedConstructor.class.getConstructor();
}
}
So, a possible solution is to either change the call to getConstructor() to include the correct type or to provide a default constructor on the object itself (but why would you do that?).
Read this: http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html
It seems that both classes Class and Constructor have the method newInstance the difference is that in the Class class you can only call newInstance with no arguments, so the called constructor must have an no arguments (this also brings a problem when you have more that one constructor).
The methoe newInstance in the Constructor class allows you to call the constructor with arguments also, notice that you can also use the method getConstructors instead of getConstructor that returns you all the class constructors and allows you to call the constructor method you want.
In this case, since you only have one constructor only and with no arguments, Class.newInstance works fine. To use the getConstructor to have the same result you'll need to add in the end oCon.newInstance();
You can use getDeclaredConstructors() which returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object
class SomeClass{
{
System.out.println("I'am here!");
}
}
public class Main {
public static void main(String[] args) throws Exception{
System.out.println(Arrays.toString(SomeClass.class.getDeclaredConstructors()));
// returns public, protected, default (package) access, and private constructors
// System.out.println(SomeClass.class.getConstructor());
// in that case you got:
// NoSuchMethodException: reflection.SomeClass.<init>()
// because SomeClass don't have public constructor
for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
constructor.newInstance();
}
}
}
And if you have private constructor like this:
class SomeClass{
private SomeClass(String val){
System.out.println(val);
}
}
You have to set accessible for constructor:
constructor.setAccessible(true);
And get something like this:
class SomeClass{
private SomeClass(String val){
System.out.println(val);
}
}
public class Main {
public static void main(String[] args) throws Exception{
for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
// constructor.newInstance("some arg"); // java.lang.IllegalAccessException
constructor.setAccessible(true);
constructor.newInstance("some arg");
}
}
}
Note: if your class declared as private his default constructor must be private too.
And be careful with nonstatic-inner classes, which receives an outer class instance
In this (somewhat convoluted) scenario, it's actually possible to get hold of the (non-public) constructor by replacing:
Constructor<?> oCon = o.getConstructor();
with
Constructor<?> oCon = o.getDeclaredConstructor();
The "default" visibility of the Jeden class (and its constructor) makes it accessible to the Start class, since it's defined in the same package.

How To invoke a Method (with java reflection) from abstract class with generic type

The Classes simplified:
public abstract class AbstractFieldGroupBind<T> {
public Class<T> beanClass;
public BeanFieldGroup<T> binder;
public void initGroupBinder(Object vaadinComponent){
binder = new BeanFieldGroup<T>(beanClass);
binder.bindMemberFields(vaadinComponent);
}
public class StammdataEditFGB extends AbstractFieldGroupBind<Cinema> {
public void pushItem(Item item) {
binder.setItemDataSource(item);
}
}
Now I try to invoke the method "initGroupBinder" by a composer Class.
If invoke the method like:
Method method = theFGBClass.getClass().getSuperclass().getDeclaredMethod("initGroupBinder", Object.class);
method.invoke(....)
If will call the class but without the Type . It will not work like this.
I also can get the generic superclass and there I find the type set in extends.
But how to bring it together to invoke the method like:
public void initGroupBinder(Object vaadinComponent){
binder = new BeanFieldGroup<Cinema>(Cinema.class);
binder.bindMemberFields(vaadinComponent);
}
ADD: I get the class "StammdataEditFGB" in the composer via Spring by context.getBean(). This construct run in a Spring Context. So also a solution with Spring's ReflectionUtils is very welcome.
Found the solution! There 2 Problems.
1. getDeclaratedMedothod will not find methods there are in extented Classes. By using getMethod you will get methods (methods must be public) in Abstract Classes.
Here a small example to show.
public class Test {
public abstract class AbstractPerson{
public void callMe(){
System.out.println("Method callMe() in AbstractPerson");
}
}
public class Person extends AbstractPerson{}
public static void main(String[] args) {
Test test = new Test();
Person person = test.new Person();
try {
Method method;
System.out.println("### Use getMethod");
method = person.getClass().getMethod("callMe", (Class<?>[]) null);
method.invoke(person, null);
System.out.println("### Use getDeclaredMethod");
method = person.getClass().getDeclaredMethod("callMe", (Class<?>[]) null);
method.invoke(person, null);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Console:
### Use getMethod
Method callMe() in AbstractPerson
### Use getDeclaredMethod
java.lang.NoSuchMethodException: Test$Person.callMe()
at java.lang.Class.getDeclaredMethod(Class.java:2004)
at Test.main(Test.java:27)
After solving that issue there has been the next one with generic type T.
2. The BeanFieldGroup could not be initialized like I did. Of course the beanClass is Null.
Here the solution with setting the beanClass for BeanFieldGroup properly:
public abstract class AbstractFieldGroupBind<T> implements IFieldGroupBind<T>{
protected BeanFieldGroup<T> binder;
#Override
public void initGroupBinder(Object view){
binder = new BeanFieldGroup<T>(getClassForT());
binder.bindMemberFields(view);
}
#Override
public void pushItem(T item) {
binder.setItemDataSource(item);
}
#Override
public T getItem() {
return binder.getItemDataSource().getBean();
}
#SuppressWarnings("unchecked")
private Class<T> getClassForT(){
Type superClazz = this.getClass().getGenericSuperclass();
Type tClazz = ((ParameterizedType)superClazz).getActualTypeArguments()[0];
return (Class<T>) tClazz;
}
}
Now it works!
When you instantiate an object of class StammdataEditFGB, you are already passing the type information to the super class. So, when you call theFGBClass.getClass().getSuperClass(), you will get a AbstractFieldGroupBind class that handles Cinema objects.

How to find the class which actually holds the element in java

Say I have two classes
class parentClass{
String myElement;
}
class childClass extends parentClass{
String notMyElemtent;
}
Now say there is an object of class childClass. Is there a way programatically tell that myElement in that object belongs to parentClass originally??
You can do it with reflection. Use obj.getClass().getField("myElement") to get Field object, representing your field.
Now you can use getDeclaringClass() method of Member interface to get class or interface actually declaring this member. So do something like this
childClass obj = new childClass();
Field field = obj.getClass().getField("myElement");
if (field.getDeclaringClass().equals(parentClass.class)) {
// do whatever you need
}
Is there a way to tell that myElement in that object belongs to parentClass originally?
Yes, you can use reflection to examine the fields of the super class:
Use Class.getSuperClass() to get the super class
Then, use
Class.getDeclaredFields() on the returned class from the above call to get a list of all fields declared by the super class
Class.getDeclaredField(String fieldName) to directly check the existence of a given field
In code, this could look like:
public static boolean belongsToParent(Object o, String fieldName) {
Class<?> sc = o.getClass().getSuperclass();
boolean result = true;
try {
sc.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
result = false;
}
return result;
}
public static void main(String[] args) {
childClass cc = new childClass();
System.out.println("myElement belongs to parentClass: " +
belongsToParent(cc, "myElement"));
System.out.println("notMyElemtent belongs to parentClass: " +
belongsToParent(cc, "notMyElemtent"));
}
Output:
myElement belongs to parentClass: true
notMyElemtent belongs to parentClass: false
Well, use getDeclaredField(name) of a class, and if its not there, try looking at its super class and so on. Works for multiple levels of inheritance:
Class<?> clazz = childClass.class;
do {
try {
Field f = clazz.getDeclaredField(fieldName);
//there it is! print the name of the super class that holds the field
System.out.println(clazz.getName());
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
} while (clazz != null);
import java.lang.reflect.Field;
public class Test4 {
public static void main(String[] args){
Child child = new Child();
System.out.println(getDeclaringClass(child.getClass(), "value"));
}
public static String getDeclaringClass(Class<?> clazz, String name) {
try {
Field field = clazz.getDeclaredField(name);
} catch (NoSuchFieldException e) {
if(clazz.getSuperclass() != null){
return getDeclaringClass(clazz.getSuperclass(), name);
}else{
return null;
}
}
return clazz.getName();
}
}
class Parent {
String value = "something";
}
class Child extends Parent {
}

Getting value of private not primitive field using reflection

Presume we have two different packages... one package can't be accessed but we like to know the value of a complex field called b.
public class A {
private String whatever;
private B b;
private static class B {
final ArrayList<Z> c = new ArrayList<Z>();
private void addItem(Z z) {
this.c.add(z);
}
private Z getItem(int nr) {
return this.c.get(nr);
}
}
}
public class Reflect extends A {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
Reflect ref = new Reflect();
Class getA = ref.getClass().getSuperclass();
Field getB = getDeclaredField("b");
getB.setAccessible(true);
Class bInst = getB.getClass();
Method bMeth = bInst.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));
}
}
How can I get the value if I don't get the complex type B from the package ?
Still get java.lang.NoSuchMethodException: stackOver.A.getItem(int) even I set the field gstB accessible ....
The only thing you are missing is that getField only gives you public accessible fields.
Field getB = getA.getDeclaredField("b");
will give you any field of that class.
A longer example
class Main {
public static class A {
private String whatever;
private B b = new B();
private static class B {
final ArrayList<String> c = new ArrayList<String>();
private void addItem(String z) {
this.c.add(z);
}
private String getItem(int nr) {
return this.c.get(nr);
}
}
}
public static class Reflect extends A {
public static void main(String... ignored) throws Exception {
Reflect ref = new Reflect();
Class getA = ref.getClass().getSuperclass();
Field getB = getA.getDeclaredField("b");
getB.setAccessible(true);
Object b = getB.get(ref);
Method addItem = b.getClass().getDeclaredMethod("addItem", String.class);
addItem.setAccessible(true);
addItem.invoke(b, "Hello");
Method getItem = b.getClass().getDeclaredMethod("getItem", int.class);
getItem.setAccessible(true);
String hi = (String) getItem.invoke(b, 0);
System.out.println(hi);
}
}
}
prints
Hello
How can I get the value if I don't get the complex type B from the package ?
You can get it as an Object, and then use reflection to further discover the methods that it exposes.
Object bInst = ... // Get b through reflection
Class bClass = bInst.getClass();
Method[] bMeth = bClass.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));
Use commons beanutils library and use following method, it is much cleaner than doing it yourself
PropertyUtils.getNestedProperty(ref, "b.propertyOfClassB");
replace propertyOfClassB with actual property name.

Categories