Understanding Java new Class[] array and implementation - java

Begining Java
Can someone break down whats going on here
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return new Class[] {
WebApplicationContextConfig.class
};
}
My understanding is that this is a method which expects its return to be an array of Class object of an unknown type
But what is the return?
An instantiation of an anonymous Class object array without a constructor and its implementation block at the same time?
What's the name of this for further reading and I can't seem to find this subject area?

There is no anonymous Class object. Class is a java class like any other, but with a name that is bound to confuse Java beginners.
the statement
return new Class[] {
WebApplicationContextConfig.class
};
is equivalent to
Class [] result = new Class[1];
result[0] = WebApplicationContextConfig.class;
return result;
WebApplicationContextConfig.class is called a class literal, and here is a some discussion about them.

It is an array declared with default values. In Java it is short-hand way of making arrays.
String[] names = {"Arvind","Aarav"}; // initialization
Now to re-assign a completely new array.
names = new String[]{"Rajesh","Amit","Mahesh"}; //re-initalization
Same thing with methods, let us say, returning days of week
public String[] weekdays(){
String[]days={"Sun","Mon","Tue"};
return days;
}
OR
public String[] weekdays(){
return new String[]{"Sun","Mon","Tue"};
}
Now about Class[], for type Class possible value is null and SomeClassName.class.
Class stringClass = String.class;
Class[] moreClasses = {Long.class, Boolean.class, java.util.Date.class};

It's just declaring an Array of Class and initialize it with one element (The Class definition of WebApplicationContextConfig)

It is array of wildcard type. See this for more

This is an array initializer. When you say
new Something[] { x1, x2, x3 }
it creates a new array of the Something class, and initializes the values to whatever you tell it in the curly braces. The length of the new array is the number of values.
I think you might be confusing it with a very similar syntax:
new Something() { class declarations, method overrides, etc. }
This one creates an anonymous subclass of Something, and it's used a lot for creating anonymous subclasses that implement interfaces. It's not at all related to the array initializer syntax, even though the appearance is pretty close.

Related

Generic list conversion to an array

Assuming that I have the following class
public class A <T>{
private T [] datas;
// more code here ...
}
And I desire to take advantage of the constructor to initialize the array. Suppose that I have the following constructor
public A(T element){....}
Java does not allow me to use something like
datas = new T[10]
And it will complain that I cannot create a generic array of T
But I can still use a work around like:
#SuppressWarnings("unchecked")
public A(T element){
List<T> datasList = new ArrayList<T>();
datasList.add(element);
datas =(T[]) datasList.toArray();
}
I have a warning from the compiler that's why I had to add the #SuppressWarnings, but my point is related to the following comment from the toArray method documentation (Please take a look at the picture)
It talks about the returned array being safe. So does that means it is safe to use this method? If not why? And what would be a better way to do such an initialisation in a constructor? I would like to also consider the case of a variable list of T elements in an overloaded constructor like
public A(T... elements){....}.
You can create an instance of a generic array using the following:
public A(T element){
int length = 10;
datas = (T[])Array.newInstance(element.getClass(), length);
}
However, there's a problem if element would be a subclass of T, e.g. if you'd call it like this:
A<Number> numberA = new A<>( Integer.valueOf(1) );
Here T would be Number but the class of element would be Integer.
To mitigate that you could pass a vararg array of type T, e.g. like this:
//firstElement only exists to force the caller to provide at least one element
//if you don't want this then just use the varargs array
A(T firstElement, T... furtherElements){
int length = 10;
Class<?> elementClass = furtherElements.getClass().getComponentType();
datas = (T[])Array.newInstance( elementClass, length);
}
Since varargs always result in an array (even of length 0) you'll get an array of type T and can get the component type of that.
So in the case above numberA.datas would be a Number[] array and not an Integer[] array.
You can pass generics, but you can't call new T (or new T[ ]).
Keep in mind that generics are gone after compilation, so it actually only helps when writing the code. Knowing it's gone during runtime, it's also obvious that new T( ) can't be called as generic, T is removed in runtime.
It's safe to do, because you create that list in full control, accepting only objects of your generic type.
A nicer way (imho) is to create a static method as it is purely input-->output. You have to declare your generics before the method return type:
public < T > T[ ] toArray(T... objects) { ... }

Why can't we create an array of "Concrete" class inside a generic class?

public class GenericClass<T> {
class MyClass {
}
public GenericClass(final T[] param) {
MyClass myObject = new MyClass(); // OK
MyClass[] myArray = { new MyClass(), new MyClass() }; // Cannot create a generic array of GenericClass<T>.MyClass
}
}
This is not creating a generic array. The compiler should have no problems understanding/determining MyClass, isn't it?
Inner classes "know" which instance of the enclosing class created them, and can access fields/members of this instance. It is as if they have a second this variable whose type is the concrete type of the enclosing class (such as GenericClass<String>).
To overcome this predicament you can make MyClass static. This will make it completely decoupled of any instance of the enclosing class (that is: it will not have that second this) so they can be instantiated freely:
public class GenericClass<T> {
static class MyClass {
}
public GenericClass(final T[] param) {
MyClass myObject = new MyClass(); // OK
MyClass[] myArray = { new MyClass(), new MyClass() };
}
}
Here's some additional information. From the link ...
Java arrays carry runtime type information that identifies the type of
the elements contained
to the compiler your code looks like this:
MyClass[] myArray = {new GenericClass<T>.MyClass(), ..} //T is unknown
The JLS section that covers this is 10.6. Specifically, it's because:
It is a compile-time error if the ClassOrInterfaceType does not denote a reifiable type (§4.7). Otherwise, the ClassOrInterfaceType may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type (§9).
The rules above imply that the element type in an array creation expression cannot be a parameterized type, other than an unbounded wildcard.
Because MyClass is non-static it is dependent on the outer class; it's actually GenericClass<T>.MyClass and therefore a parameterized type. Declaring it static removes that dependency and solves the problem.
Where it gets weird is if you do this;
class MyClass<T> {
}
public GenericClass(final T[] param) {
MyClass[] myArray = { new MyClass(), new MyClass() };
}
It's legal. Screwy, kind of clumsy, but legal. Because you redeclare the type, it hides the outer one. Then ... arrays and generics don't mix ... unless you use raw types. For backward compatibility you can have a rawtype array which ends up holding MyClass<Object>. It's a really awful thing, but it does compile. You can get away with creative casting here but in the end ... just ... don't.
{ new MyClass(), new MyClass() }; //new MyClass() => new GenericClass<T>.MyClass()
Above code will be treated as array of object as T is unknown ,due to the way generics are implemented (by erasure), the type of the array is not well-defined. On one hand, it should be an array of MyClass , on the other hand, it should be an array of Object
Create array of object type and cast it to your type
Object[] arr=new Object[]{this.new MyClass(), this.new MyClass()};
MyClass[] myArray = Arrays.copyOf(arr,arr.length, Item.MyClass[].class);
If you make it static it will work because-
A static nested class or nested interface (which is always static, by the way) has no relation to its outer class (or interface) apart from namespace nesting and access to private variables.
As an example in the standard API, look for the interface Map.Entry, nested inside the interface Map, yet has no access to its type parameters and needs to declare them again.
The problem here is that the compiler cannot determine at compile time the information of the array myArray. It is considered generic because (as eclipse shows you) it is converted in {new GenericClass<T>.MyClass(), ...}. This is because you're putting the class MyClass inside a generic class.
This code doesn't work either:
package my.stuff;
public class GenericClass<T> {
class MyClass {
static MyClass[] myArray = { new MyClass(), new MyClass() };;
}
public GenericClass(final T[] param) {
MyClass myObject = new MyClass();
}
}
but this code works:
package my.stuff;
public class GenericClass<T> {
public GenericClass(final T[] param) {
MyClass myObject = new MyClass();
MyClass[] myArray = { new MyClass(), new MyClass() };
}
}
class MyClass {
}
Because you're not using generics in your MyClass, the best thing to do is probably the second one.
If you declare it static, the compiler knows that MyClass is not generic and it knows what to do.
Besides, the only way to create a generic array in java is create a raw type and then cast it to generics (see here: "Cannot create generic array of .." - how to create an Array of Map<String, Object>?). So, if you absolutely need myClass inside the generic one, you should turn it in MyClass<T>, and then you use the trick: create a raw type and cast it to MyClass<T>:
package my.stuff;
public class GenericClass<T> {
class MyClass<T> {
}
#SuppressWarnings("unchecked")
public GenericClass(final T[] param) {
MyClass<T> myObject = new MyClass<T>();
MyClass<T>[] myArray = new MyClass[]{ new MyClass<T>(), new MyClass<T>() };
}
}
even it you don't use T inside the class MyClass.
#ItayMaman has the right reason. Basically, MyClass is not a reifiable type.
MyClass is a non-static inner class. Since it is non-static, it is within the scope of the type parameters of its enclosing class. And every time you write MyClass by itself in an instance method of GenericClass, it is actually short for GenericClass<T>.MyClass. So even though it may not look it, MyClass (by itself) is actually a parameterized type (parameterized by T), similar to List<String>. And so when you do new MyClass[2], you are trying to create an array of a parameterized type, just like new List<String>[2]. And I think you already know that this is not allowed.
What should you do? It all depends on what your intention is. One thing that people suggest is to make MyClass static. Of course, that will take it out of the scope of T. But that may or may not be what you want, because it completely changes its relation to GenericClass. A non-static inner class has access to an instance of the enclosing class, which is perhaps why you made it that way in the first place. If you never intended for it to be non-static (and did it by mistake), then this is obviously the way to go.
If a non-static inner class is what you want, and you simply wants to create an array of this type, let's consider how you would usually deal with arrays of parameterized types, e.g. List<String>[].
One solution is to instead create an array of the raw type, e.g. List[] foo = new List[2];. The equivalent way to do this for our case would be GenericClass.MyClass[] foo = new GenericClass.MyClass[2];. Notice what we did here. In order to write the raw type, we had to explicitly qualify MyClass with the unparameterized outer class name. If we didn't explicitly qualify it, then it would be implicitly qualified with GenericClass<T>, as explained above, which is not what we want. Translating this to the code in your example, you would write GenericClass.MyClass[] myArray = { new MyClass(), new MyClass() };
Similarly, if we want to avoid raw types, we could create an array of the wildcarded type, e.g. List<?>[] foo = new List<?>[2];. The equivalent way to do this for our case would be GenericClass<?>.MyClass[] foo = new GenericClass<?>.MyClass[2];. So translating this to the code in your example, you would write GenericClass<?>.MyClass[] myArray = { new MyClass(), new MyClass() };
Finally, we might instead want to create an array of the wildcarded type, but then cast back into an array of the parameterized type, for convenience of use later on. e.g. List<String>[] foo = (List<String>[])new List<?>[2];. The equivalent way to do this for our case would be MyClass[] myArray = (MyClass[])new GenericClass<?>.MyClass[] { new MyClass(), new MyClass() };. Note the the cast is an unchecked cast. The advantage of this is now when you get things out of myArray, it will be type MyClass, instead of raw type GenericClass.MyClass or wildcarded type GenericClass<?>.MyClass from the methods above.

Get object's class and its constructor, Reflection in Android

suppose i have classA and classB(generic), reference http://www.exampledepot.com/egs/java.lang.reflect/Constructors.html
I am passing a customobject from classA to classB, now i am wanting constructor of customobject in classB and call it
classA
customclass objCustomclass;
classB mClassB;
mClassB.getConstructorAndCall(objCustomclass);
classB
public void getConstructorAndCall(Object objCustomclass);
try {
Object filledObject = objCustomclass.getClass().newInstance();
// here i need to call filledObject's contructor
} catch (Exception e) { }
I am able to create object as the instance of custom object but what about constructor.
note: getConstructorAndCall() is a commom method and in that object is of unknown type that means any class can pass its object.
Thanks.
well if the constructor is empty, then I think that what you have should run the constructor. Anything more complicated, like, passing parameters to the function can be done through:
Constructor[] constructors = objCustomClass.getClass().getConstructors()
for (int i = 0; i < constructors.length; i++) {
Constructor c = constructors[i];
Class[] paramTypes = c.getParameterTypes();
Object[] params;
// do fancy stuff here - it helps if you know what the constructors take beforehand
Object filledObject = c.newInstance(params);
}
Constructor with parameters
From the JavaDoc for java.lang.Class ( http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#newInstance() ):
Creates a new instance of the class represented by this Class object.
The class is instantiated as if by a new expression with an empty
argument list. The class is initialized if it has not already been
initialized.
I. E. the newInstance() method always uses the default constructor.
Most times I see people using new instance and requiring a particular constructor or signature, it happens to be due to a lack on the solution design. You might want to double check if a pattern applies to the solution you need.

Class[] - What does it mean?

I'm looking at a tutorial found on: http://www.ibm.com/developerworks/library/j-dyn0603/
In particular there is a section where it gives the following example:
Class[] types = new Class[] { String.class, String.class };
Constructor cons = TwoString.class.getConstructor(types);
Object[] args = new Object[] { "a", "b" };
TwoString ts = (TwoString)cons.newInstance(args);
I don't quite follow what Class[] represents. The way I read it, this says 'an array of Class objects called types]. I'm also somewhat unfamiliar with the syntax used in the new statements - how does new Class[] { String.class, String.class} work?
If someone can help break this down for me I would appreciate it.
Yes the literal meaning is exactly what you are thinking it is
Class[] types = new Class[] { String.class, String.class }; is a declaration and initialization in one line. It says create an array that holds objects of type Class and initialize it with two objects of type Class, namely String.class and String.class.
A similar example would be
int[] nums = new int[]{1,2,3};
or
float[] decimals = new float[]{1.2, 3.1, 5.2}
A Class is an Object that describes a java class (or interface). A Class[] is an array of these objects.
The syntax <ClassName>.class (e.g. String.class) returns the Class for a particular java class (or interface).
A new array can be created through a few syntax. new Class[i] creates a new array of Class with length i and filled with default values (null references). new Class[]{a, b, c} creates a new array of Class containing the given elements a, b and c. It's length is 3 because 3 elements were given.
That's an array of the type Class
The
new Class[] {...}
Creates and array of type Class whose contents are listed inside.
In general
Type[] means, an "array of..." just like you thought.
It turns out the type here is Class which in Java is a representation of a running class or interface.
Probably you shouldn't go for advanced features like reflection without knowing first the basics.
It is an array of Objects which share the super type Class.
In Java, everything is an Object. This means that if you want to have in-code awareness of class types, you need to create an Object which can encapsulate the details of the class. Java calls this Object a Class.
Note the capitalization and be aware that since Class is an Object, you can call all Object methods on class, like x.getClass(), x.wait(), and x.hashcode().
Class[] items = { String.class, Integer.class };
means create an array called items which contains Class objects. Initialize the array with the Objects representing the class of String and the class of Integer.
Since Class objects represent class types, often the two are used interchangeably in informal speech.
Class is actually a class named, uhmm.. Class.
Instances of the class Class represent classes and interfaces in a running Java application.
new Class[] works. It initializes an array of Class references. But, as usual with object arrays, the references are null.
Class Class does not have a public constructor. So you can not say new Class()
Class is a java class that represents ... a class and related metadata. so Class[] is an array of Class objects.
Each class in java has a static member variable named class of type Class and here what you're doing is
creating a Class[] containing two
members each of which is an object of
type Class and specifically the Class
representing java.lang.String
looking up via reflection the
reference to the constructor in the
class TwoString that takes two
java.lang.String objects =>
TwoString(String, String)
creating an object array to feed to
the constructor with the values "a"
and "b"
finally you're creating an instance
of TwoString ts by invoking the
constructor you looked up in (b) and
args you initialized in (c)
This is equivalent to:
TwoString ts = new TwoString("a","b");
but the way you've posted is using Reflection/Introspection.
I am not sure if this is what you are looking for, but the Class[] in the example is mimicking the constructor in that TwoString class. To me it would have been clearer if they would have used two different types. So if the TwoString class looked like this:
public class TwoString {
private String m_s1;
private Integer m_s2;
public TwoString(String s1, Integer s2) {
m_s1 = s1;
m_s2 = s2;
}
}
The class name would not make since anymore, but I think that is easy to fix. The rest of the code example would become:
Class[] types = new Class[] { String.class, Integer.class };
Constructor cons = TwoString.class.getConstructor(types);
Object[] args = new Object[] { "a", 1 };
TwoString ts = (TwoString)cons.newInstance(args);
So the class array is to set up the constructor to use. The steps line by line are:
The class array sets up what constructor to use.
Then you find the constructor.
The you set up what values to pass into the constuctor.
Then you call the constructor to create the instance.

Generics in Java, using wildcards

I have a question about Generics in Java, namely using wildcards. I have an example class GenClass like this:
public class GenClass<E> {
private E var;
public void setVar(E x) {
var = x;
}
public E getVar() {
return var;
}
}
I have another simple class:
public class ExampleClass {
}
I have written the following test class:
public class TestGenClass {
public static void main(String[] str) {
ExampleClass ec = new ExampleClass();
GenClass<ExampleClass> c = new GenClass<ExampleClass>();
c.setVar(ec);
System.out.println(c.getVar()); // OUTPUT: ExampleClass#addbf1
}
}
Now, if I use a wildcard and write in the test class this:
GenClass<?> c = new GenClass<ExampleClass>();
on the place of:
GenClass<ExampleClass> c = new GenClass<ExampleClass>();
the compiler has no problem with this new statement, however, it complains about
c.setVar(ec);
It says that "the method (setVar()) is not applicable for the arguments (ExampleClass)". Why do I get this message?
I thought that the way I have used the wildcard, makes the reference variable c be of type GenClass, which would accept as parameter any class - on the place of E I would have any class. This is just the declaration of the variable. Then I initialize it with
new GenClass<ExampleClass>()
which means that I create an object of type GenClass, which has as parameter a class of type ExampleClass. So, I think that now E in GenClass will be ExampleClass, and I would be able to use the method setVar(), giving it as argument something of type ExampleClass.
This was my assumption and understanding, but it seems that Java does not like it, and I am not right.
Any comment is appreciated, thank you.
This exact situation is covered in the Java Generics Tutorial.
Notice that [with the wildcard], we can still read elements from [the generic Collection] and give them type Object. This is always safe, since whatever the actual type of the collection, it does contain objects. It isn't safe to add arbitrary objects to it however:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.
(emphasis mine)
mmyers has the correct answer, but I just wanted to comment on this part of your question (which sounds like your rationale for wanting to use the wildcard):
I thought that the way I have used the wildcard, makes the reference variable c be of type GenClass, which would accept as parameter any class - on the place of E I would have any class. This is just the declaration of the variable. Then I initialize it with
If you really want to accomplish this, you could do something like without compilation errors:
GenClass<Object> gc = new GenClass<Object>();
gc.setVar(new ExampleClass());
But then again, if you want to declare an instance of GenClass that can contain any type, I'm not sure why you'd want to use generics at all - you could just use the raw class:
GenClass raw = new GenClass();
raw.setVar(new ExampleClass());
raw.setVar("this runs ok");

Categories