find class of array (String[].class --> String.class) [duplicate] - java

Object o = new Long[0]
System.out.println( o.getClass().isArray() )
System.out.println( o.getClass().getName() )
Class ofArray = ???
Running the first 3 lines emits;
true
[Ljava.lang.Long;
How do I get ??? to be type long? I could parse the string and do a Class.forname(), but thats grotty. What's the easy way?

Just write
Class ofArray = o.getClass().getComponentType();
From the JavaDoc:
public Class<?> getComponentType()
Returns the Class representing the component type of an array. If this class does not represent an array class this method returns null.

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getComponentType():
public Class<?> getComponentType()
Returns the Class representing the component type of an array. If this class does not represent an array class this method returns null...

#ddimitrov is the correct answer. Put into code it looks like this:
public <T> Class<T> testArray(T[] array) {
return array.getClass().getComponentType();
}
Even more generally, we can test first to see if the type represents an array, and then get its component:
Object maybeArray = ...
Class<?> clazz = maybeArray.getClass();
if (clazz.isArray()) {
System.out.printf("Array of type %s", clazz.getComponentType());
} else {
System.out.println("Not an array");
}
A specific example would be applying this method to an array for which the component type is already known:
String[] arr = {"Daniel", "Chris", "Joseph"};
arr.getClass().getComponentType(); // => java.lang.String
Pretty straightforward!

Related

Create object using Java reflection

I receive from an external source strings that are pretty much the signature of the constructor of the object. They contain the class name and the parameters.
For example:
public class Foo {
public Foo(int x, int y, int z) {
// do something
}
}
public class Bar {
public Bar (int x, boolean bool) {
// do something
}
}
Let's say I have many classes like this, and I want to create object from these classes based on the string I receive (that contains the class name and the paramters). Can this be done?
I know I can get the class using something like this:
String className = "myClass";
Class<?> myClass = Class.forName(className);
//Constructor<?> ctor = myClass.getConstructor();
//Object object = ctor.newInstance(new Object[] { ctorArgument });
But how can I instantiate the object if I don't know at compile time how many paramters the constructor will have and of which type they will be? By the way, the classes from which I want to create the object will most likely have only one constructor available. But each class might have a different constructor compared to the other.
No problem because the newInstance() method receives an array:
public T newInstance(Object ... initargs)
So you just initialize an array containing all the arguments and pass it
something like this:
String[] argsAsString = readValuesFromString(data);
Object[] args = new Object[argAsString.length()];
int i = 0;
Class<?>[] paramTypes = ctor.getParameterTypes();
for (String argStr: argsAsString) {
args[i] = convertStringToActualType(argStr, paramTypes[i]);
i++;
}
ctor.newInstance(args);
You probably need to call getConstructors() on the class and then try to find the constructor with the correct number of arguments. This will work only if you dont have two or more constructors with the same number of arguments.
Then the convertStringToActualType() should know how to convert the string value to the actual parameter.. for example if it's boolean field `Boolean.valueOf(argStr)' etc - example:
Object convertStringToActualType(String arg, Class<?> type) {
if (type == String.class)
return arg;
if (type == Boolean.class)
return Boolean.valueOf(arg);
throw new IllegalArgumentException("type " + type.getSimpleName() + " not supported");
}

'[L' prefix in Java reflection

Using Java6 reflection API, Class.getDeclaredFields returns pretty weird values. Example of class field:
protected String[] arrF = new String[15];
Using getDeclaredFields on proper Class, a Field is returned:
name = arrF
type = [Ljava.lang.String;
The question: does [L prefix mean that the arrF is an array? Can I always rely on that, i.e. the field is an array iff type is prefixed with [L? If no, how can I get some information about "arrayness" of the field?
[ means one-dimension array ([[ is 2 dimensions array), and L followed by the class/interface name (Lclassname) is the type of that array.
See Class#getName().
Can I always rely on that, i.e. the field is an array iff type is prefixed with [L?
Yes. Or better, use Class#isArray().
This is a much better way to do it!
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import static java.lang.System.out;
public class ArrayFind {
public static void main(String... args) {
try {
Class<?> cls = Class.forName(args[0]);
Field[] flds = cls.getDeclaredFields();
for (Field f : flds) {
Class<?> c = f.getType();
if (c.isArray()) {
// ....
}
}
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
Btw. byte[] has name [B - [L is there for longs and/or references.
What you got is so called binary name. Binary name is able to represent an array type as arrays in Java do not implement or extend an Array-like interface.
[Ljava.lang.String; means:
[ single dimensional array
L array of reference types and not primitives
java.lang.String; represents the component type of the array

Java: How to get Values of an Enum Class from an Generic Type Object instance?

I want to create an Enum editor, which takes an Enum type as its generic.
E is a generic type, but restricted to be an Enum type. How can I get the values of the Enum class from the instance e?
public class ComboBoxEnumEditor<E extends Enum<E>>{
public ComboBoxEnumEditor(E e) {
// how to get values of E from e?
// attemp1:
List values = e.getClass().values();
// attemp2:
List values = ((Enum.class)e.getClass()).values();
// attemp3:
List values = ((Enum.class)e.getClass()).values();
// none of the above works...
}
}
Say I have an Enum
public enum Location {
Default( false, EAttributeLocation.MAIN_TABLE_IF_AVAILABLE ),
Main( false, EAttributeLocation.MAIN_TABLE ),
Overflow( false, EAttributeLocation.OVERFLOW_TABLE ),
Separate( false, EAttributeLocation.SEPARATE_TABLE );
......
}
I want my ComboBoxEnumEditor be able to do
{
ComboBoxEnumEditor(new Location());
}
Please help, thanks.
It looks like you are looking for (but I may be mistaken)
Enum[] values = e.getClass().getEnumConstants();
or as mentioned by #pbabcdefp in this answer (big +1 for him) if you would like to have E[] instead of Enum[]
E[] values = e.getDeclaringClass().getEnumConstants();
Also based on
...which takes an Enum Class as its generic
your argument should probably be Class<E> clazz not E e itself so you could use it with ComboBoxEnumEditor(Location.class);. In that case you could simply use
E[] values = clazz.getEnumConstants();
E[] arr = e.getDeclaringClass().getEnumConstants();
Short answer... You can't. Doing this is not valid syntax since you can't instantiate an enum:
ComboBoxEnumEditor(new Location());
Instead, you need to pass the class of your enum and change your method signature for that, e.g.
ComboBoxEnumEditor(Location.class);

I cannot instantiate an object of class Integer in my code (Java)

I am creating a class, Doubly Linked List with ListNode as innerclass.
public class DoublyLinkedList<Integer> {
/** Return a representation of this list: its values, with adjacent
* ones separated by ", ", "[" at the beginning, and "]" at the end. <br>
*
* E.g. for the list containing 6 3 8 in that order, return "[6, 3, 8]". */
public String toString() {
String s;
ListNode i = new ListNode(null, null, *new Integer(0)*);
Why is it that I get the error, cannot instantiate the type Integer?
The Integer in your class definition is generic type parameter which hides the Integer wrapper class.
So, new Integer(0) you use inside the class is taking Integer as type parameter, and not the Integer type itself. Since, for a type parameter T, you can't just do - new T();, because the type is generic in that class. Compiler doesn't know what type exactly it is. So, the code is not valid.
Try changing your class to:
public class DoublyLinkedList<T> {
public String toString() {
ListNode i = new ListNode(null, null, new Integer(0));
return ...;
}
}
it will work. But I suspect that you really want this. I guess you want to instantiate the type parameter inside your generic class. Well, that's not possible directly.
You pass the actual type argument while instantiating that class like this:
DoublyLinkedList<Integer> dLinkedList = new DoublyLinkedList<>();
P.S: It would be better if you explain your problem statement clearly, and put some more context into the question.

Cast Object array to Custom Class array

i created a class derived of Object and I have a object array.
how to do cast object array to my class array?
public class CastArray{
public CastArray(){
}
public long toLong(){
return Long.parseLong(this.toString());
}
public double toDouble(){
return Double.parseDouble(this.toString());
}
public int toInteger(){
return Integer.parseInt(this.toString());
}
}<br />
return Error:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LBasic.CastArray;
The question is a bit vague but let me make an attempt to answer it. if the object array is actually an array of your class, you can do a direct cast to your array e.g. A[] a = (A[]) objArray;. Alternatively, if you know that each element can be cast into your class (is an instance of your class or one of its sub classes), you can clone it by creating a new array and adding each element with a cast to your class. e.g.:
A[] a = new A[objArray.length];
int i = 0;
for (Object o : objArray) {
a[i++] = (A) o;
}
It sounds like you're asking how to do this:
Object[] objectArray = {};
CastArray castArray = (CastArray)objectArray;
If this is the case you can't.
The Arrays.copyOf(...) could be a solution for you.
Best regards!

Categories