Calling a Method that has Generic Parameters - java

I am trying to understand some source code. How do I call this method in main?
public void introSort(T[] array, int max_depth)
{
System.out.println(array.length);
}
I simply want to return the length of the given array in my main method. If this is any help, the method is in a class with this declaration:
public class IntroSort<T extends Comparable<T>> extends AbstractSort<T> {
[I understand that this is of generic type, but my understanding of that concept in Java is too minimal for me to answer my questions.]

The type of the array element is the type variable T of the class IntroSort. This is an example for an instance of IntroSort with the type parameter set as Integer:
Integer[] array = {1, 2, 3, 4};
IntroSort<Integer> obj = new IntroSort<>();
obj.introSort(array, 1);
The compiler would match T with Integer based on the declaration of IntroSort, which also means that the array must be of type Integer.

The T is just referring back to the T in your class specification.
If you have an instance of IntroSort, just call the method on it with the same type of array as you instantiated the class with.

Related

Java Array with the same name as a class name

I really can't find any information about it that's why I'm asking here.
I'm trying to figure out what is it type of Array if it has same name as a class... like:
public class ArrayOne {
int SomeInt;
ArrayOne [] arr;
public ArrayOne(SomeInt){
arr=new ArrayOne[1];
}
}
Maybe someone know where can I read about it. Thanks a lot
If you declare an array like this:
int[] myIntArray = new int[3];
you have an array of int (remember that int in java is not an object)
So if you write:
ArrayOne[] arr;
You will have an array of object from class ArrayOne.
If you are still in doubt, you can check an array type like this:
Class ofArray = o.getClass().getComponentType();
take a look here : http://docs.oracle.com/javase/8/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.
That would be an array of that classes objects.
Your arr variable will be of Array type, which contains objects of ArrayOne type.
If the question is around naming, then your array is named arr but not after the class which it is typed with.

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) { ... }

length of array of private class is not accessible

Please consider the following code :
class A {
B[] arr = new B[10];
private class B {}
}
class C {
void fun(){
A a = new A();
Object arr = a.arr;
Object len = a.arr.length; // !! ERROR
}
}
As I written in code. a.arr.length; is giving error.
I actually understand why it is happening. It is because sub class B is private. But still why it is happening. In class A, property arr was accessible, but why not it's length. Is there any explanation for this in jls or anywhere.
I just want a clear explanation for this behaviour. I know private things cannot be accessed outside of its class. But a public array could be. No matter of what type it is. And if anything is accessible outside, then its public properties should also be accessed. But here it is not happening.
Edit : I found that in C# it is not even possible to create an array of private class. In java if we cannot access anything, and cannot even know the length of the array of private class then what is the use of creating an array of private class.
The reason for this is a combination of two statements in the JLS:
Item 6.6.1 Determining accessibility:
An array type is accessible if and only if its element type is accessible.
This means that if T is private, T[] is also considered private.
Item 10.7 Array members:
The public final field length, which contains the number of components of the array. length may be positive or zero.
Remember that accessibility is determined at compile-time based on the type of reference you have, not on the type of the actual object!
Now, let's go into a little more elaborate example to demonstrate what this means. I added a toString() and a constructor to B.
class A {
B[] arr = { new B(1), new B(2), new B(3), new B(4) };
B plain = new B(99);
private class B {
public int i;
B(int i) {
this.i = i;
}
#Override
public String toString() {
return "Hidden class B(" + i + ")";
}
}
}
Now, in class C, we use:
A a = new A();
Object plain = a.plain;
String s = plain.toString();
This is legal, because a.plain is a visible field. s will contain Hidden class B(99). But if you try:
String s = a.plain.toString(); // Compile error
This will not be allowed, because althogh toString() in B is public, B itself is private, you have no access to its members, whether public or private.
Note that we cannot access i in B despite its being public. If we use:
plain.i
Then since i is not a member of Object, you get a compile error. And if we use:
a.plain.i
Then since a.plain is private, you can't access its members, as we already tried.
So now we go and look at the issue of arrays. Suppose we write:
Object[] objArr = a.arr;
int len = objArr.length;
This is legal, despite the fact that objArr is internally A.B[]. We have a reference to Object[], Object is public and so is Object[]. But:
int len = a.arr.length;
Gives you a compile error exactly as we got for a.plain.toString(). Although length is public in itself, you are accessing it through a reference to A.B[]. A.B[] is not accessible because A.B is not accessible. And therefore, because length is its member, you cannot access it. You simply cannot access any member of a reference type that is not visible to you, by the first rule above.
It is interesting to note that the following is legal:
Object firstItem = a.arr[0];
We can use the expression a.arr[0] because it is not considered an attempt to access a member of the array. The elements of the array are not considered to be members in it. a.arr[0] is simply an expression on an array reference that resolves to type A.B. There is no problem with such an expression as long as we don't try to access members of the item.
firstItem.toString() // Good
a.arr[0].toString() // Bad
Summary
It's OK to get hold to a reference to a private type, provided you cast it to some public supertype.
It's OK to get a specific item in an array of a private type. Indexing the array is not considered "accessing a member", it's just an expression on a reference that gives you a reference to its member type. Which you'll need to cast to something public in order to use.
It's not OK to try accessing a member with a given reference to a private type, even if the member is public. This includes the length of an array.
It's OK to access that public member through a cast to a supertype if it's available in that supertype. length is available in Object [] so you can get it through that.
It's not possible to access a public member of a private type that doesn't exist in an accessible supertype.
Do this:
class A {
B[] arr = new B[10];
public int getArrayLength()
{
return arr.length;
}
private class B {}
}
class C {
void fun(){
A a = new A();
Object arr = a.arr;
//Object isn't type safe
//Object len = a.getArrayLength();
int len = a.getArrayLength();
}
}
According to JavaDocs
At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modifiers: private and protected. The private modifier specifies that the member can only be accessed in its own class. The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.
Knows that the question is about accessing the length field. But, it was interesting for me to find that the length can be determined by enhanced-for-loop, not by making changes to access privileges or using reflection:
int length = 0;
for(Object o : a.arr) {
length++;
}
Few interesting statements about arrays were:
Arrays
In the Java programming language, arrays are objects (§4.3.1), are
dynamically created, and may be assigned to variables of type Object
(§4.3.2). All methods of class Object may be invoked on an array.
Array Types
An array's length is not part of its type.

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.

In Java, is it possible to use a type variable, as an array element, inside an Interface?

In Java, is it possible to use a type variable, as an array element, inside an Interface?
I've tried as a filed type and as a cast operator, but always get the error
Cannot make a static reference to the non-static type A
interface ITest<A> {
A[] j; // Cannot make a static reference to the non-static type A
Object[] = (A[]) new Object[3]; // Cannot make a static reference to the non-static type A
}
Is there any case, where I am able to use the construct A[] inside the interface (and in an enum type?)?
class CTest<A> {
enum MyEnum {
F, G, H;
// something that uses A[] inside. Getting the same error as above
}
}
You can use a generic array type in an interface, like this:
public interface Foo<T> {
void doSomething(T[] array);
}
Your problem was you were trying to declare a field in an interface, which you basically can't do other than for constants. You can't declare a field of a generic array type in an interface, but I'd hope that you wouldn't want to anyway.
Admittedly type erasure makes the combination of arrays and generics somewhat awkward in various situations, but I think the above at least answers the question you posed.
Fields in interfaces are implicitly public, static and final, they're basically constants. And you can't have constants that depend on a type parameter because in Java parameters are removed from the type on compilation.
By the way, this is independent of whether you're using an array or not,
public interface X<T> {
T c = (T)new AnyType();
}
won't work either. And neither would
public class X<T> {
public static final T c = (T)new AnyType();
}

Categories