How to find the class which actually holds the element in java - 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 {
}

Related

Get Java type from String [duplicate]

I have a String which has a name of a class say "Ex" (no .class extension). I want to assign it to a Class variable, like this:
Class cls = (string).class
How can i do that?
Class<?> cls = Class.forName(className);
But your className should be fully-qualified - i.e. com.mycompany.MyClass
String clsName = "Ex"; // use fully qualified name
Class cls = Class.forName(clsName);
Object clsInstance = (Object) cls.newInstance();
Check the Java Tutorial trail on Reflection at http://java.sun.com/docs/books/tutorial/reflect/TOC.html for further details.
You can use the forName method of Class:
Class cls = Class.forName(clsName);
Object obj = cls.newInstance();
You can get the Class reference of any class during run time through the Java Reflection Concept.
Check the Below Code. Explanation is given below
Here is one example that uses returned Class to create an instance of AClass:
package com.xyzws;
class AClass {
public AClass() {
System.out.println("AClass's Constructor");
}
static {
System.out.println("static block in AClass");
}
}
public class Program {
public static void main(String[] args) {
try {
System.out.println("The first time calls forName:");
Class c = Class.forName("com.xyzws.AClass");
AClass a = (AClass)c.newInstance();
System.out.println("The second time calls forName:");
Class c1 = Class.forName("com.xyzws.AClass");
} catch (ClassNotFoundException e) {
// ...
} catch (InstantiationException e) {
// ...
} catch (IllegalAccessException e) {
// ...
}
}
}
The printed output is
The first time calls forName:
static block in AClass
AClass's Constructor
The second time calls forName:
The class has already been loaded so there is no second "static block in AClass"
The Explanation is below
Class.ForName is called to get a Class Object
By Using the Class Object we are creating the new instance of the Class.
Any doubts about this let me know
It should be:
Class.forName(String classname)
Not sure what you are asking, but... Class.forname, maybe?
public static Class<?> getType(String typeName) {
if(typeName.equals("Date")) {
return Date.class;
} else if(typeName.equals("Float")) {
return Float.class;
} else if(typeName.equals("Double")) {
return Double.class;
} else if(typeName.equals("Integer")) {
return Integer.class;
}
return String.class;
}

Creating a class and creating an instance from a string

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 + "]";
}
}
}

is it possible to declare a Java Class variable using getClass()?

All of the relevant classes in my application instantiate a version of the class Logger as logger = new Logger(). Any class can invoke it's instance of logger.setText(String text).
The writeText(Object parameter) method in ClassA is built to get the previously set string from each class instance of logger by invoking it's instance of logger.getText().
Currently I've placed a conditional inside wrtieText for each of the classes. This works, but can become an issue if I end up adding more classes. I want a catch-all writeText method to accommodate for any new classes that may be added.
The following is the currently working model. Beneath this, I have included the alternate version of ClassA, which attempts to do what I'm describing by using the getClass() method.
ClassA.java
public class ClassA {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.execute();
}
public void execute() {
ClassB doSomething = new ClassB();
writeText(doSomething);
ClassC doSomethingElse = new ClassC();
writeText(doSomethingElse);
}
public void writeText(Object parameter) {
if(parameter instanceof ClassB) {
ClassB x = (ClassB) parameter;
System.out.println(x.logger.getText() + "\n\n");
}
if(parameter instanceof ClassC) {
ClassC x = (ClassC) parameter;
System.out.println(x.logger.getText() + "\n\n");
}
if(parameter instanceof ClassD) {
ClassD x = (ClassD) parameter;
System.out.println(x.logger.getText() + "\n\n");
}
}
}
Logger.java
public class Logger {
private String text = "";
public void setText(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
ClassB.java
public class ClassB {
Logger logger = new Logger();
public ClassB() {
logger.setText("Hello from ClassB!");
}
}
ClassC.java
public class ClassC {
Logger logger = new Logger();
public ClassC() {
logger.setText("Hello from ClassC!");
}
}
I'm trying to invoke the getClass() method in order to account for any class with the following, but it's running into some problems.
ClassA.java
public class ClassA {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.execute();
}
public void execute() {
ClassB doSomething = new ClassB();
writeText(doSomething);
ClassC doSomethingElse = new Class();
writeText(doSomethingElse);
}
public void writeText(Object parameter) {
Class aClass = parameter.getClass();
// now what? The following doesn't work as expected
aClass x = (aClass) parameter;
System.out.println(x.logger.getText());
}
}
No, what you are trying to do will not work. Variable types need to be declared with a known type at compile time.
Use proper encapsulation.
Define an interface HasLogger (or whatever name fits best) which defines a method getLogger that returns a Logger value. Make your classes ClassA, ClassB, etc. implement this interface.
Change your writeText method to accept an argument of type Loggable and then just get the Logger
public void writeText(HasLogger parameter) {
System.out.println(parameter.getLogger().getText());
}
Yes, it is possible to do it with reflection. You might iterate the fields and then call your method on a Logger field. Something like,
public void writeText(Object parameter) {
Class<?> aClass = parameter.getClass();
for (Field f : aClass.getDeclaredFields()) {
if (f.getName().equals("logger")) {
try {
f.setAccessible(true);
Logger log = (Logger) f.get(parameter);
System.out.println(log.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

How to invoke parent private method from child? [duplicate]

This question already has answers here:
How can a derived class invoke private method of base class?
(7 answers)
Closed 7 years ago.
public class A{
private int getC(){
return 0;
}
}
public class B extends A{
public static void main(String args[]){
B = new B();
//here I need to invoke getC()
}
}
Can you please tell me if it is possible to do sush thing via reflection in java?
class A{
private void a(){
System.out.println("private of A called");
}
}
class B extends A{
public void callAa(){
try {
System.out.println(Arrays.toString(getClass().getSuperclass().getMethods()));
Method m = getClass().getSuperclass().getDeclaredMethod("a", new Class<?>[]{});
m.setAccessible(true);
m.invoke(this, (Object[])null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
EDIT:
This is quiet an old post but adding a few nuggets of advice
Reconsider your design
Calling private method of parent, though possible through Reflection, but should not be done. Calling private methods on parent might leave the class in invalid state and may lead to unexpected behaviors.
You can do it using reflection, but unless there is a very good reason to do so, you should first reconsider your design.
The code below prints 123, even when called from outside A.
public static void main(String[] args) throws Exception {
Method m = A.class.getDeclaredMethod("getC");
m.setAccessible(true); //bypasses the private modifier
int i = (Integer) m.invoke(new A());
System.out.println("i = " + i); //prints 123
}
public static class A {
private int getC() {
return 123;
}
}
You should declare getc protected. That's exactly what it's for.
As for reflection: Yes, it is possible. You'd have to call setAccessible on the method object though. And it's bad style... ;-)
getDeclaredMethod will only return the private methods in the current class not the inherited methods. To achieve it you need to navigate the inheritance graph via the getSuperclass method. Here is a code snippet that does it
private Method getPrivateMethod(Object currentObject) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> currentClass = currentObject.getClass();
Method method = null;
while (currentClass != null && method == null) {
try {
method = currentClass.getDeclaredMethod("getC");
} catch (NoSuchMethodException nsme) {
// method not present - try super class
currentClass = currentClass.getSuperclass();
}
}
if (method != null) {
method.setAccessible(true);
return method;
} else {
throw new NoSuchMethodException();
}
}
you can try like this using reflection:
Method getCMethod = A.class.getDeclaredMethod("getC");
getCMethod.setAccessible(true);
getCMethod.invoke(new A());

Casting a Object into Reflected Class and Method

A normal form of what I am trying is this.
MyClassFacadeLocal cls = new MyClassFacadeLocal();
List allMyClass = cls.findAll();
Iterator it = allMyClass.iterator();
while(it.haxNext()) {
MyClass Obj = (MyClass)it.next();
out.println(obj.getTitle());
}
Now, the problem I am creating a global method, which can handle several cases of this. For this, I will pass the Entity Class name, method name and the List that is return by the .findAll() method. How to solve this using the reflection. What I tried was really rough and of course didn't work.
List allMyClass; //I will have passed this before
Iterator it = allMyClass.iterator();
while(it.hasNext()) {
try {
Class<?> c = Class.forName(this.getEntityClassName());
c.cast(it.next());
Method method = c.getDeclaredMethod("getTitle");
String title = method.invoke(c, null).toString();
} catch(Exception e) {
}
}
Gives: "object is not an instance of declaring class" error. But I am confident this is a usage flaw.
Really, you shouldn't use reflection to do that. Make all your entities implement a common interface with a getTitle() method:
public interface HasTitle {
public String getTitle();
}
public class MyClass1 implements HasTitle {
// ...
#Override
public String getTitle() {
return this.title;
}
}
public class MyClass2 implements HasTitle {
// ...
#Override
public String getTitle() {
return this.title;
}
}
...
/**
* This method can be invoked withg a List<MyClass1> or with a List<MyClass2>
* as argument, since MyClass1 and MyClass2 both implement HasTitle
*/
public void displayTitles(List<? extends HasTitle> entities) {
for (HasTitle entity : entities) {
out.println(entity.getTitle();
}
}
Your code does too much work by using Class.forName and uses the wrong reflection method getDeclaredMethod -- that one doesn't take into account the inherited methods. The c.cast line doesn't do anything -- it merely asserts that the object is an instance of its own class.
Use this code:
public static void printProp(List<?> xs, String methodName) {
try {
for (Object x : xs)
System.out.println(x.getClass().getMethod(methodName).invoke(x));
} catch (Exception e) { throw new RuntimeException(e); }
}
The first glance flaw I see is that you don't assign the
c.cast(it.next());
to new variable.

Categories