Java run time class reflection - java

Say if I have a class named Car I can use the following line of code in certain situations.
Car.class
My question is there a way I can make the same type of call if a user supplies a class name at run time. Have tried something similar to the below but no joy, is there a way i can do it.
String className = "Car";
Class.forName(className ).class;
Also I need to be able to cast dynamically, if the user specifies a list of objects I need to be able to dynamically cast.
e.g. instead of Car myCar = (Car) object
I need to be able to have to the user specify the name/type of class at run time so that I need to be able to do something along the lines of ClassName myObj = (ClassName) object.

Class.forName("Car") already returns the same as Car.class.
For casting, you can then use Class.forName("Car").cast(object), which would return a Car object. Take a look at the API, mostly the java.lang.Class part of it.
Also, since you're casting # runtime, there's no type safety, and you should check whether object extends or implements Car before doing it, otherwise you'll get an exception. A question I asked ~ a year ago and the answers there may be relevant to you as well.
Though, as others already said, this smells & you could probably redesign it in a better way, also note that this type of casting will typically be pretty slow because Java needs to examine the type hierarchy (it needs to throw a ClassCastException if it can't cast to Car).

Given the nature of the question, most of the answers to this are straight from the Reflection API documentation. I would suggest you take a look at this: http://docs.oracle.com/javase/tutorial/reflect/class/index.html. If this does not help and you need help with something specific, we can look at that.

What you are looking for is a feature called Reflection in the Java programming language.
It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
A Simple Example from http://java.sun.com
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
For an invocation of:
java DumpMethods java.util.Stack
the output is:
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
Here is an example of creating objects at runtime:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
You can read more about it here and here - for indepth view
Also look here:
What is reflection and why is it useful?

You want to interact with myObj, so rather than going through these gymnastics, think about adding an interface that models the interactions you want to have with the objects, then use that interface in the code. The classes supplied by the user can then be validated to implement the necessary interface and errors raised appropriately.

The expression Car.class returns the java.lang.Class object for class Car.
A statement Class.forName("Car") will also return the java.lang.Class object for class Car (assuming that class Car is in the default package). Note: No need to append .class; that would give you the Class object of class Class itself, which is not what you want.
Class Class has methods to check if an object is an instance of the class that the Class instance represents (hope this is not too confusing...). Since you don't know the name of class Car at compile time, you're not going to have any kind of compile time type safety.
Lookup the API documentation of java.lang.Class.

Related

Trying to get superclass from extended class

Trying to pass only the parent class data from the extended class in a function.
public class ParentClass {
String pageNo;
}
public class ExtendClass extends ParentClass {
String lineNo;
}
In another class i'm trying to
dosomething(...){
savePage((ParentClass)extendClass);
}
savePage(ParentClass pclass){
.....
}
But when i look into the function savePage arguments i can still see lineNo which i don't want to see.
UPDATE
I have added debug pic of the issue i was facing. Even after downcasting to PageApi, i still see "elements" which exist in BoardPage class
It seems to me that what you are trying to achieve is impossible.
If you create an instance of ExtendClass, then that instance always has a lineNo field.
When you explicitly cast or implicitly convert the type ExtendedClass to ParentClass, you don't change the actual instance in any way. At runtime, the instance has that lineNo field ... in all cases. Now the compiler won't let code within the body of the savePage method see or refer to that field (unless the code first casts the reference back to the type ExtendedClass), but the field will be there nonetheless.
You are examining the instances using a debugger. A debugger doesn't follow the rules able what fields should be visible. It sees everything, and it shows you everything. And, it clearly shows you the reality ... that the field is really there.
So ... is there a way to make the field go away entirely? Or hide it from the debugger?
Answers: No, and No.
(Warning: this is tangential to the original question, and probably beyond the OP's understanding.)
Should there be a way to make the field go away? From a language design perspective?
Answer: No.
Consider this code as a "thought experiment":
ExtendedClass ec = new ExtendedClass();
ec.lineNo = 42;
ParentClass pc = (ParentClass) ec; // Actually the cast is redundant
ExtendedClass ec2 = (ExtendedClass) pc;
System.err.println("The old line no is " + ec.lineNo);
System.err.println("The new line no is " + ec2.lineNo);
If (hypothetically) casting from ExtendedClass to ParentClass actually removed a field, then when you cast back to ExtendedClass the field value would no longer be there. But what should ec2.lineNo actually contain? And how could it be different to ec.lineNo ... unless we had actually created a completely new object when we did the type cast(s)?
Thinking it through, if an explicit or implicit type cast created a new object, then you couldn't effectively do polymorphism. Polymorphism depends on being able to operate on a given object from the viewpoints of either its true type or one of its supertypes. If creating that view actually creates a new object ... it simply doesn't work ... unless Java was a pure functional language; i.e. no mutation.
In short, while it might possibly be an attractive idea for a small number of use-cases, this idea would fundamentally break Java as an OO language.
This is my example for the short answer I gave above
import java.lang.reflect.Field;
public class Parenting {
static public class ParentClass {
String pageNo;
public ParentClass() {}
public ParentClass(final ParentClass pOriginal) { // copy CTOR
pageNo = pOriginal.pageNo;
}
}
static public class ExtendClass extends ParentClass {
String lineNo;
}
public static void main(final String[] args) throws IllegalArgumentException, IllegalAccessException {
final ParentClass pc = new ParentClass();
pc.pageNo = "page #7";
final ExtendClass ec = new ExtendClass();
ec.pageNo = "page#24";
ec.lineNo = "line #25";
analyze("Pure Parent", pc);
analyze("Cast Parent", ec);
analyze("Copy Parent", new ParentClass(ec));
}
static private void analyze(final String pTitle, final ParentClass pAnalyzeObject) throws IllegalArgumentException, IllegalAccessException {
System.out.println("Analyzing " + pTitle + ":");
Class<?> p = pAnalyzeObject.getClass();
while (p != Object.class) {
for (final Field f : p.getDeclaredFields()) {
System.out.println("\t" + p.getName() + "\t" + f.getName() + "\t\"" + f.get(pAnalyzeObject) + "\"");
}
p = p.getSuperclass();
}
}
}

Why the cast is necessary in this case?

class MyClass {
private String str;
public MyClass(String str){
this.str = str;
}
public int compare(Object o) {
return str.compareTo(((MyClass)o).str); //line No.8
}
}
class Client {
public static void main(String[] args) {
MyClass m = new MyClass("abc");
MyClass n = new MyClass("bcd");
System.out.println(m.compare(n));
}
}
Why in this snippet of code the cast (MyClass)o in line number 8 is necessary, despite the fact that the Client invokes a compare method with arguments which are instances of MyClass class?
When I modify the compare method in MyClass class to form like below:
public int compare(Object o) {
System.out.println(o.getClass());
System.out.println(((MyClass)o).getClass());
return str.compareTo(((MyClass)o).str);
}
Then, the Client will produce the following result:
class MyClass
class MyClass
Thus I don't understand why the cast above is required and why I can't just do like that (without cast to MyClass):
public int compare(Object o) {
return str.compareTo(o.str);
}
Because when I do that, I get the compile time error:
str cannot be resolved or is not a field
This comes down to what the compiler knows at compile time. At compile time it knows that what is going to be passed into this method is of type Object. That means that it can guarantee the methods that are associated with the class Object, but not the methods of type MyClass.
Because that compare method takes any argument of type Object, or a subclass, you could pass anything in. What if I make a class MyOtherClass like this..
public class MyOtherClass {
public String notStr;
}
And I do something like..
MyOtherClass myOtherClass = new MyOtherClass();
MyClass myClass = new MyClass();
myClass.compare(myOtherClass);
Without the cast, you've now got a situation where at runtime, it attempts to access a field that is not there. The cast is put in place to guarantee that the object is of the correct type, or it will fail before it attempts to access that field.
Just as an Aside
I've been working extensively with a language called Groovy. It is a language that essentially sits on top of Java, but it supports things like dynamic binding and loose typing (which is what you're after here). If this kind of functionality is a must have for you, then I would recommend checking out the documentation.
o's type in compare is an Object. This means the parameter it could be a MyClass instance, but it also could not. Object doesn't have any field called str (as that one belongs to MyClass), so there's no way to get that field from it, and so the code can't compile. If you cast to MyClass, however, it will have a field called str, and so it will be able to access it.

Declare new class from a Variable in Java

I would like to know if there is a way to do something like this in Java:
Integer a = new Integer(2);
a.getClass() newVariable = new Integer(4);
My question is can I declare the type of a new variable by using a variable?
It is not possible to specify the type by retrieving it from an other variable.
Note that the reflection tutorial of Oracle provide some methods that would simulate it. It will allow you to instantiate an object by specifying it type as a class. But that won't allow you to first specify the object type by retrieving it from the variable.
You might want to have a look at generics which would probably help you fix the hidden problem that made you ask this question.
A simple example would be
public class Foo<T> {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Note that T stands for Type as per the documentation.
#param the type of the value being boxed
So you can give any type.
You can also specify the extends of the type, which kind of give you some security.
class Foo<T extends Integer>
No, you cannot base the type of a variable on the type of another variable like that.
Depending on your real goal, you might be able to use Java's generics to get around your reason for feeling you want to do that, but it depends a lot on what your real end goal is. For instance, if this is all in class Foo, you could parameterize it, and then use the parameter in both places:
class Foo<T> {
public method doSomething() {
T a = /*...*/;
T newVariable = /*...*/;
}
}
Then:
Foo<Integer> f = new Foo<Integer>();
...results in an f with a doSomething that works with and returns Integers.
Note the /*...*/ after the = in the above: I can't do new T() there, which is a famous limitation of Java's generics. The values for a and newVariable would have to come from somewhere (arguments to the method, for instance, or data members, etc.).
More about generics here, again depending on whether they really help with what you're ultimately trying to do.

Keeping track of all instances of a subclass in the superclass

I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.

Java - array of different objects that have the same method(s)

I am practicing inheritance.
I have two similar classes that I'd like to assimilate into one array, so I thought to use the Object class as a superclass since everything is a sublcass of Object.
So, for example I put T class and CT class into an array called all like so:
Object all[] = new Object[6];
all[0] = T1;
all[1] = CT2;
all[2] =T3;
all[3] = CT1;
all[4] = T2;
all[5] = CT3;
I skipped the declarations as thats not my problem.
My real issue becomes when I wish to call a function within the array utilizing a loop:
for (int i = 0; i < 6; i++) {
all[i].beingShot(randomNum, randomNum, AK47.getAccuracy());
}
The classes involved with T and CT respectively both have the beingShot method, which is public.
Eclipse advises casting them as a quick fix. I'm wondering if there is any logical alternative other than creating my own Object class that holds the beingShot method, or adding this to the class of Object, although I feel either of these choices would cause more problems in the long run.
Thanks!
If both classes implement the same method(s), you should consider creating an interface.
Interfaces are very powerful and easy to use.
You could call your interface Shootable.
You can create an array of different objects that implement Shootable and treat them all the same.
// Define a VERY simple interface with one method.
interface Shootable {
public void beingShot();
}
// Any class that implements this interface can be treated interchangeably
class Revolver implements Shootable {
public void beingShot() {
System.out.println("Revolver: firing 1 round");
}
class MachineGun implements Shootable {
public void beingShot() {
System.out.println("Machine Gun: firing 50 rounds");
}
}
class HockeyPuck implements Shootable {
public void beingShot() {
System.out.println("Hockey Puck: 80 MPH slapshot");
}
}
class RayBourquePuck implements Shootable {
public void beingShot() {
System.out.println("Hockey Puck: 110 MPH slapshot");
}
}
class OunceOfWhiskey implements Shootable {
public void beingShot() {
System.out.println("Whiskey Shot: 1 oz down the hatch...");
}
}
// You can declare an array of objects that implement Shootable
Shootable[] shooters = new Shootable[4];
// You can store any Shootable object in your array:
shooters[0] = new MachineGun();
shooters[1] = new Revolver();
shooters[2] = new HockeyPuck();
shooters[3] = new OunceOfWhiskey();
// A Shootable object can reference any item from the array
Shootable anyShootableItem;
// The same object can to refer to a MachineGun OR a HockeyPuck
anyShootableItem = shooters[0];
anyShootableItem.beingShot();
anyShootableItem = shooters[2];
anyShootableItem.beingShot();
// You can call beingShot on any item from the array without casting
shooters[0].beingShot();
shooters[1].beingShot();
// Let's shoot each object for fun:
for (Shootable s : shooters) {
s.beingShot();
}
Here's a great related question and answer.
Object doesn't have the method beingShot. If all of the objects in array are of the same class, then your array should be of that same class. Otherwise they all should have same interface implemented or extend the same class. I can't imagine why would you want explicitly extend Object here, it doesn't add any functionality whatsoever.
You need to typecast your object references to appropriate class to call their method..
For each reference you fetch from your array, you need to check using instanceof operator, of which is the instance referred to by your object reference.. Accordingly you can typecast the reference to that class..
But Typecasting is an ugly thing.. You should avoid it as far as possible.. If you have to choose which method to invoke based on exact sub class, you should probably go with an Interface.. It is the best way you can achieve what you want here...
And I think you have got enough information about how to implement it..
You cant do it...since Java does not support extension method. (C# does)
READ THE LINK BELOW:
Java equivalent to C# extension methods

Categories

Resources