Sign in to follow this  
cptrnet

[java] generics problem

Recommended Posts

I am trying to learn generics but it gives me an error when I try to compile this code. It says
<T>printScores(T[]) in ArrayTest cannot be applied to (int[])
printScores(testScores);
^

public class ArrayTest{

	public static <T> void printScores(T[] scores){
		for(T t : scores){
			System.out.println(t);
		}
	}

	public static void main(String[] args){
	
		int[] testScores;
		testScores = new int[4];
	
		printScores(testScores);
	
	}
	
}

I know that I have a local array that doesn't have anything in it yet so I don't know if that's the problem or not, but I am sure it will be down the road. If anyone can help me I would appreciate it very much, Thanks.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
maybe you have to explicitly instantiate it?


public static void main(String[] args){

int[] testScores;
testScores = new int[4];

printScores<int>(testScores);

}

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
maybe you have to explicitly instantiate it?

*** Source Snippet Removed ***



public static void main(String[] args){

int[] testScores;
testScores = new int[4];

printScores<int>(testScores);

}




I forgot to loggin :(

VetroXL

Share this post


Link to post
Share on other sites
Last time I checked, Java generics did not support primitive types, only things descended from Object. So no int.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Last time I checked, Java generics did not support primitive types, only things descended from Object. So no int.


Okay so there is the answer right there.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Last time I checked, Java generics did not support primitive types, only things descended from Object. So no int.


Actually, primitive types have been supported since the Generics system was first introduced. Auto-boxing was implemented at the same time, so anywhere an object is expected you can pass a primitive type and it will be auto-boxed to an instance of the class for that type (int will be promoted to Integer, float to Float, and so on).

Share this post


Link to post
Share on other sites
Quote:
Original post by cptrnet
I am trying to learn generics but it gives me an error when I try to compile this code. It says

*** Source Snippet Removed ***



*** Source Snippet Removed ***

I know that I have a local array that doesn't have anything in it yet so I don't know if that's the problem or not, but I am sure it will be down the road. If anyone can help me I would appreciate it very much, Thanks.


While primitive types can be auto-boxed to object instances when used singly, this apparently doesn't work for arrays of primitive types. What you'll have to do is make an array of Integer objects and use it instead:


public class ArrayTest{

public static <T> void printScores(T[] scores){
for(T t : scores){
System.out.println(t);
}
}

public static void main(String[] args){

Integer[] testScores = new Integer[4];

// you can populate the array with regular ints- they
// will automatically be converted to Integer objects
for(int i=0; i<4; ++i)
testScores[i] = i;


printScores(testScores);

}

}


Share this post


Link to post
Share on other sites
Quote:
Original post by Kevinator
Interesting find. Do you think that was intentional?


I'm sure it was, but I can only guess as to why. I'm sure it has to do with the fact that arrays are objects themselves. Conceptually, you can think of an array of ints as a type of IntArray, and array of Integers as a type of IntegerArray. All arrays expose the public methods of Object, implement the Cloneable interface, and have a public final field called length. I imagine that this adds some amount of complexity to auto-boxing from a primitive aray to an Object array, and likely would involve too much overhead to do behind the scenes.

Share this post


Link to post
Share on other sites
you coud try the following:


static void print(List<? extends Object> list) {
for(Object o : list)
System.out.print(o + " ");
}

static List<Integer> asList(int... values) {
final int[] _values = values;

return new java.utial.AbstractList<Integer>() {
public Integer get(int index) {
return _values[index];
}
public int size() {
return _values.length;
}
};
}

public static void main(String... args) {
// primitive type int array
int [] array = { 0, 1, 2, 3};
print(asList(array));

// wrapper class integer array
Integer [] array2 = { 4, 5, 6, 7};
print(java.util.Arrays.asList(array2));
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Aldacron
Quote:
Original post by Kevinator
Interesting find. Do you think that was intentional?


I'm sure it was, but I can only guess as to why. I'm sure it has to do with the fact that arrays are objects themselves. Conceptually, you can think of an array of ints as a type of IntArray, and array of Integers as a type of IntegerArray. All arrays expose the public methods of Object, implement the Cloneable interface, and have a public final field called length. I imagine that this adds some amount of complexity to auto-boxing from a primitive aray to an Object array, and likely would involve too much overhead to do behind the scenes.
actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky.and extremely easy to screw up. This is somewhat of a contrived example, but the fact that it is possible and not caught at compile time is extremely disconcerting:


ArrayList<String> a = new ArrayList<String> ();
Object b = a;
ArrayList c = (ArrayList) b;
c.add (new Integer (23)); //<-- no bomb
System.out.println (a.get (0)); //<-- BOMB!


Share this post


Link to post
Share on other sites
Quote:
actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky.and extremely easy to screw up. This is somewhat of a contrived example, but the fact that it is possible and not caught at compile time is extremely disconcerting:


ArrayList<String> a = new ArrayList<String> ();
Object b = a;
ArrayList c = (ArrayList) b;
c.add (new Integer (23)); //<-- no bomb
System.out.println (a.get (0)); //<-- BOMB!


This behavior is intentional to ensure for backward compatibility for both, using >= Java 1.5 libs with Java <= 1.4 and using Java <= 1.4 libs with Java >= 1.5.

If you had watched you compiler output, you would have reading the following note:

Note: XXX.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

The details are:
XXX.java:line: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.ArrayList
which is exaclty your bomb, the 'add' method not the 'get' one!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:

actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky


Err.. considering that generics is 100% backwards-compatible it's pretty far from incredibly flaky. In fact it's very well designed.

What would you have done differently, without breaking things?

Quote:

and extremely easy to screw up.

Funny, I've used generics nearly everyday for since it was introduced and not once have I screwed it up.

And what you are doing in your example is just plain stupid, not to mention the fact that you ignored the compiler warnings completely.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Quote:

actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky


Err.. considering that generics is 100% backwards-compatible it's pretty far from incredibly flaky. In fact it's very well designed.

What would you have done differently, without breaking things?


Personally, I would've defined a separate set of generic containers, and let the existing ones unmodified. Then, when using generics, I would have made the compiler supply the type paramater(s) as a hidden data member(s), so that some additional runtime checking is possible (using assertions, so that you could turn it on and off, if speed would matter). This would also make the creation of arrays of type T possible, etc.

Share this post


Link to post
Share on other sites
Quote:
Original post by SamLowry
Quote:
Original post by Anonymous Poster
Quote:

actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky


Err.. considering that generics is 100% backwards-compatible it's pretty far from incredibly flaky. In fact it's very well designed.

What would you have done differently, without breaking things?


Personally, I would've defined a separate set of generic containers, and let the existing ones unmodified. Then, when using generics, I would have made the compiler supply the type paramater(s) as a hidden data member(s), so that some additional runtime checking is possible (using assertions, so that you could turn it on and off, if speed would matter). This would also make the creation of arrays of type T possible, etc.

Yes, and considering that 1.5 apps rarely run on a 1.4 VM flawlessly, I would have scrapped any plans to keep it backwards-compatible.

Share this post


Link to post
Share on other sites
Quote:
Original post by capn_midnight
Quote:
Original post by SamLowry
Personally, I would've defined a separate set of generic containers, and let the existing ones unmodified. Then, when using generics, I would have made the compiler supply the type paramater(s) as a hidden data member(s), so that some additional runtime checking is possible (using assertions, so that you could turn it on and off, if speed would matter). This would also make the creation of arrays of type T possible, etc.

Yes, and considering that 1.5 apps rarely run on a 1.4 VM flawlessly, I would have scrapped any plans to keep it backwards-compatible.


Personally, I'm very happy that there are *not* two versions of container casses like in .Net 2.0, however this is more a matter of taste..
but regardings the backward compatibility it really works 100% if developers are doing things right. For example using Foo<T extends Object & OtherType> instead of Foo<T extends OtherType> and so on..

Anyway, this is how Java has been changed and you have t live with it => your arguments in the previous post still don't count, as the compiler warns you not being type safe..

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this