Java type-casting -- Q3

G

grz01

... The code you wrote made my eyes bleed ...

OK, Mark, since I dont want to
risk anyones physical wellbeing :)
I'll re-phrase the question
(starting from scratch with a new thread).

The problem I started out with was from a real programming task.

I wanted to make a static function
that returns a Pair of Lists,
where the first component
(lets say, for simplicity)
is known to be: List<Integer>
and the other component is: List<String>

So the return-type really should be:
Pair<List<Integer>,List<String>>

But since I dont think Java has any type for Pair<A,B> (?) and I dont
like to create yet another custom-class only for this trivial purpose,
I decided instead to try a return-type like either

List<List<Object>> or
List<List<?>>

where the "returnvalue.get(0)" is of type List<Integer>
and "returnvalue.get(1)" is of type List<String>
(is there a better candidate for a return-type, without creating a new
class?)

Now, if I try:

public static List<List<Object>> returnListList() {

List<List<Object>> result = new ArrayList<List<Object>>();

List<Integer> iList = new ArrayList<Integer>();
// ... add some objects to iList...
List<String> sList = new ArrayList<String>();
// ... add some objects to sList...

result.add(iList);
result.add(sList);

return result;
}

the .add() method-calls give a type-error.
And it also does *not* work to try this instead:

result.add((List<Object>)iList);
result.add((List<Object>)sList);

Of course, I could declare iList and sList as List<Object> instead,
but I would really like to keep the type-info there, for clarity.

After some experimentation, I found this one *does* works:

public static List<List<?>> returnListList01() {

List<List<?>> result = new ArrayList<List<?>>();

List<Integer> iList = new ArrayList<Integer>();
// ... add some objects to iList...
List<String> sList = new ArrayList<String>();
// ... add some objects to sList...

result.add(iList);
result.add(sList);

return result;
}

But unfortunately, the last function gives me a problem when I try to
*consume* it, and extract the two lists from the returnvalue.

If I do

public static void consume(){
List<List<?>> myList = returnListList();
List<Integer> iList = (List<Integer>)myList.get(0);
List<String> sList = (List<String>)myList.get(0);
}

I again get the warning:

Type safety: Unchecked cast from List<capture#1-of ?> to
List<Integer>

And I dont seem to be able to rewrite it, without getting some other
error or warning.

Any hints, what is the best way to do what I want to achieve? I.e
return a pair of lists of known, but different types (without
creating a new class) and then split the returnvalue into the two
separate lists?

/ grz01
 
J

Joshua Cranmer

But since I dont think Java has any type for Pair<A,B> (?) and I dont
like to create yet another custom-class only for this trivial purpose,
I decided instead to try a return-type like either

List<List<Object>> or
List<List<?>>

Just bite the bullet and make Pair<A, B>. What you're trying to do is
more or less to negate the purpose of generics.
 
G

grz01

Correction:

Where I wrongly wrote:

public static List<List<?>> returnListList01() { // WRONG

it should be:

public static List<List<?>> returnListList() { // RIGHT

/ grz01
 
G

grz01

Just bite the bullet and make Pair<A, B>. What you're trying to do is
more or less to negate the purpose of generics.

Well... no... still not my choice here... what Im writing is a library
of static methods, that other people can use, too, and I really would
prefer it to distribute as one single class.

At least, I dont want to give it up only for this silly little
issue...
 
L

Lew

grz01 said:
I'll re-phrase the question
(starting from scratch with a new thread).

I gave a detailed answer on the List-of-List matter in another thread with a
code example. Don't use wildcards in return types; use generic methods or
classes.

Others contributed many detailed answers to the subject as well.

You were given links to at least five strong articles on the topic.

Have you read the articles? The responses? They provide very important
background before you can approach the Pair <T, U> question.

....
So the return-type really should be:
Pair<List<Integer>,List<String>>

But since I dont think Java has any type for Pair<A,B> (?) and I dont

It's very easy to write one.
like to create yet another custom-class only for this trivial purpose,

What, you want to save your talents for the hard problems?

If it's so trivial, why'd you go with a complex, ill-understood and
excessively tricky approach instead?

Now you launch into Usenet with the exact same issues we've already answered
for you:
I decided instead to try a return-type like either

List<List<Object>> or

This tells you that the base type is 'Object'. Each list-list element can be
of a different subtype of 'Object'. You are proving only 'Object'ness about
the base type.
List<List<?>>

This tells you that the base type is some subtype of 'Object', not necessarily
'Object' itself. All list-list elements must be of the same base type, call
it 'capture#1-of ?'.

We've explained all this in detail before.

The referenced articles we've already mentioned explain all this in detail.

....
I again get the warning:

Type safety: Unchecked cast from List<capture#1-of ?> to
List<Integer>

And I dont seem to be able to rewrite it, without getting some other
error or warning.

Use generic types instead of wildcards. Use Pair said:
Any hints, what is the best way to do what I want to achieve? I.e
return a pair of lists of known, but different types (without
creating a new class) and then split the returnvalue into the two
separate lists?

Let us know that you have finished reading the posts and material already
provided, first.

Then use an approach like:

public final class Pair <T, U>
{
private final T gauche;
private final U droit;
public Pair( T g, U d )
{
gauche = g;
droit = d;
}
public T getGauche() { return gauche; }
public U getDroit() { return droit; }
}

public class Test
{
private final List <Pair <Integer, String>> intestrins
= new ArrayList <Pair <Integer, String>> ();

public Test()
{
intestrins.add( new Pair <Integer, String> ( 1.0, "one" );
}
public List <Pair <Integer, String>> getIntestrins()
{
return intestrins;
}
}

Please do report back that you've read the responses we've already given,
including now this one, and the articles we've linked for you.

For your convenience, just in case it's too much trouble for you to go back to
yesterday's posts in the "Java type-casting -- Q1" thread, in particular the
responses to you from Peter Duniho and me wherein we first cited them, at
22:16Z and 23:32Z, I repeat in this post the article links we provided:

<http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html>
<http://java.sun.com/docs/books/tutorial/java/generics/wildcards.html>
<http://java.sun.com/docs/books/effective/generics.pdf>
<http://www.ibm.com/developerworks/java/library/j-jtp04298.html>
<http://www.ibm.com/developerworks/java/library/j-jtp07018.html>
 
L

Lew

Well... no... still not my choice here... what Im writing is a library
of static methods, that other people can use, too, and I really would
prefer it to distribute as one single class.

At least, I dont want to give it up only for this silly little
issue...

He's given you the right advice. You reject it, then come back and ask the
same question again.

If you already know better, why are you asking us?

Besides, you could do it as a single class with Pair as a nested type.
 
M

markspace

grz01 said:
Any hints, what is the best way to do what I want to achieve? I.e
return a pair of lists of known, but different types (without
creating a new class) and then split the returnvalue into the two
separate lists?


I agree with Lew. Make a public Pair class static inside your class,
and then just return that type. Once you do that the problem becomes
easy. If you really need to manipulate types that are totally unknown,
it's possible, but rather tricky to get right, and never faster than the
type safe code.

My IDE wrote the entire Pair class for me, btw, except for the first
three lines.

Note that there's no casts (and no warnings) anywhere in this code.


package fubar;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MyStuff {

public static void main( String[] args )
{
Pair<List<Integer>,List<String>> lists = makeLists();
consume( lists.getFirst() );
consume( lists.getSecond() );
}

public static class Pair<A,B> {
private final A first;
private final B second;

public Pair( A first, B second )
{
this.first = first;
this.second = second;
}

public A getFirst()
{
return first;
}

public B getSecond()
{
return second;
}
}

public static Pair<List<Integer>,List<String>> makeLists() {
List<Integer> intList = new ArrayList<Integer>(
Arrays.asList( 1, 2, 3 ) );
List<String> strList = new ArrayList<String>(
Arrays.asList( "a","b","c" ) );
return new Pair<List<Integer>,List<String>>( intList, strList );
}

public static void consume( List<?> list ) {
for( Object o : list ) {
System.out.println( o );
}
}

}
 
J

John B. Matthews

Well... no... still not my choice here... what Im writing is a
library of static methods, that other people can use, too, and I
really would prefer it to distribute as one single class.
[...]

Besides, you could do it as a single class with Pair as a nested
type.[/QUOTE]

This valuable recommendation has several advantages. The OP may want to
look at the relevant tutorial:

<http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html>

I had previously overlooked the link to this compelling diagram:

<http://blogs.sun.com/darcy/entry/nested_inner_member_and_top>

As another example, this simple drawing program consists of a single
class. It uses static member classes, non-static member classes and an
anonymous classes; it uses no local classes:

<http://sites.google.com/site/drjohnbmatthews/graphpanel>
 
R

Roedy Green

But since I dont think Java has any type for Pair<A,B> (?) and I dont
like to create yet another custom-class only for this trivial purpose,

That's just the way Java is. Get an IDE that will generate all the
getter/setter/constructor/private field bubblegum for you and hold
your nose.

That is the proper way to do it. You get type safety and fairly
readable code (ignoring the boilerplate Pair class).

You can use an Object[] to create a quick and dirty Pair. Sun does
this sometimes, e.g. in Dimension.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Civilisation advances by extending the number of important operations which we can perform without thinking about them."
~ Alfred North Whitehead (born: 1861-02-15 died: 1947-12-30 at age: 86)
 
M

markspace

Roedy said:
You can use an Object[] to create a quick and dirty Pair. Sun does
this sometimes, e.g. in Dimension.

Since he's using generics, this will still result in an "unchecked" warning.

Object[] objs = new Object[2];
objs[0] = new ArrayList<String>();
List<String> list = (List<String>) objs[0]; // unchecked

That last line will produce the warning the OP is concerned about. A
generic Pair class will eliminate the warning altogether.
 
G

grz01

You were given links to at least five strong articles on the topic.
Have you read the articles?  

Greetings Lew! :)

Yes, thank you for the links!
Im still struggling with them, and the reason I decided to re-post
(including some more background for the actual problem I had)
was that I still didnt find (and still dont see)
the both elegant enough an practical enough solution I was hoping for.

Admittedly, my understanding of "generics",
is most likely a bit clouded by the fact that
I worked in the past for many years with
the pure polymorphic type-systems of functional languages,
which I always found totally sound, elegant,
and very easy and intuitive to work with.

While generics on the surface look very similar,
I start realize now that they are also guite more
different and trickier than I thought before
getting into this...

And I also now start to suspect that "generics" is
kind of a "poor man's solution to polymorphism"
(not as bad as for example Perls laughable
implementation of what they claim to be "OOP",
but still.... :)

Anyways, what I find quite curious,
is that with all those wonderful and "sci-fi" features
with which they bloated Java over the years,
for some reason, apparently,
they never arrived at the point of
adding a very basic and useful thing like
java.util.Pair<A,B> to the standard library.

Anyone has a clue why?

Or even better, define a general type like
java.lang.Tuple<T1, ..., Tn>

While I guess you cannot define such a type
within the existing language today (or am I wrong?),
I dont see that there would be any theoretical
problems with coding it into the compiler-core,
with some new syntax for denoting tuples, etc.
Again, feel free to correct me,
if you think Im wrong.

/ grz01
 
J

Joshua Cranmer

Or even better, define a general type like
java.lang.Tuple<T1, ..., Tn>

That's an easy one to answer: Java does not have variable-argument
generic types.
 
G

grz01

That's an easy one to answer: Java does not have variable-argument
generic types.

I know.
Thats why I wrote you would have to code this feature
into the compiler-core, thus extending the current language a bit.

Would it actually break anything -- or cause any real problems?
I dont think so -- or am I wrong?

Otherwise I think it would be a very useful thing to do.
 
J

Joshua Cranmer

I know.
Thats why I wrote you would have to code this feature
into the compiler-core, thus extending the current language a bit.

Would it actually break anything -- or cause any real problems?
I dont think so -- or am I wrong?

Specifying how it would work is not simple. The closest analogue is
variable-arity methods, which uses an array as its actual storage. I
know C++0x has support for such a feature, but emulating its approach
without having template specialization is more than a bit annoying.

Such a feature is nice in theory, but the practical aspect is more or
less a deal-breaker. Variable-argument generic types has very little use
outside of tuples, so adding such a complex feature for so little
benefit is probably not worth it.
 
L

Lew

grz01 said:
And I also now start to suspect that "generics" is
kind of a "poor man's solution to polymorphism"

What the heck do you mean by that? Are you saying that polymorphism is a
problem to which generics is the solution in Java? Or are you saying that
generics is a substitute in Java for polymorphism? Because neither is even
remotely true.

Are you aware that Java has had polymorphism since its inception, well before
generics, and that generics expands and supplements the power of polymorphism?
Admittedly, my understanding of "generics",
is most likely a bit clouded by the fact that
I worked in the past for many years with
the pure polymorphic type-systems of functional languages,
which I always found totally sound, elegant,
and very easy and intuitive to work with.

I also find it interesting that you compare generics to functional languages.
Generics are not set up to express the same sorts of things that functional
syntaxes do, although they're slightly similar in that both are declarative.
But generics are much more narrow in focus - their only purpose is to declare
proofs about type relationships, and they're strictly compile time.

And again, polymorphism is a fundamental aspect of Java.

I am curious how else one might consider expressing a base-type relationship
like "list of String" in Java were generics not available.

As to your complaint that Pair<A, B> is not yet in the Java API, two posters
have responded to you with implementations of such a class demonstrating how
truly trivial it is to add to your code. It's hardly a show-stopping omission.

markspace's implementation is all of 20 lines long, without Javadocs, and he
implemented it as a nested class to handle your strange objection to writing
more than one top-level class:
public static class Pair<A,B> {
private final A first;
private final B second;

public Pair( A first, B second )
{
this.first = first;
this.second = second;
}

public A getFirst()
{
return first;
}

public B getSecond()
{
return second;
}
}

Maybe it's time to stop whining that someone else didn't write your code for
you and just go ahead and write your own code. Isn't that what you're paid
for? To be able to write code? Or do you want Sun and this newsgroup to do
your job for you? Shouldn't we get paid by your employer if we do?
 
G

grz01

I'd say it's the "limited benefit" that prevails ...
... Why spend time adding the class,  
even as simple as it could be, to address a non-need like that?

Well, as to "spend time", I just wonder how many minutes would
it actually take to add it once and for all in the std lib?

I mean, how unusual is it that you need e.g. to define
a function that returns two or more different things of
different types?

Any opinion is as good as any other opinion I guess,
but how much time have java-programmers globally
and collectively spent either:

1) Defining yet another silly, "one-off" JavaBean class,
only for holding the two or more values.
or

2) writing their individual and mutually
incompatible, almost identical versions of
my.useful.goodies.package.Pair<A,B>
or
my.other.goodies.package.Triple<A,B,C>
or

3) utilizing the call-by-reference nature
of Java-method Object-parameters, to do
something really stupid
or

4) (like me now) deciding instead to use either
List<Object> or Map<sometype,Object> for
representing a tuple,
or

5) <suggest you own workaround methods>

only because a very basic and useful feature
is simply missing in the std lib?

My own firm opinion is that you are *grossly*
underestimating the "limited benefit".

If you are programming Java,
and you seriously think about it,
I am actually sure you have already suffered
many times yourself from this missing feature,
without even realizing it.

/ grz01
 
G

grz01

Lew,

First, I suggest you simply stop reading my postings if they make you
so upset -- no good for your health... :)

Second, from what I can see, what they call "polymorphism" in Java, is
something totally different from polymorphism in the functional
languages that I have been working with (Haskell, ML, etc).

/grz01
 
L

Lew

Patricia said:
private static List<List<? extends Object>> someMethod(){

(More succinctly: 'List <List <?>>')

Patricia, for the particular reason you already stated:
It gives up some type safety, and so is
definitely not a solution I would choose or seriously recommend.

I want to highlight a point I've run across in my reading.

One of the rules of thumb is, "Don't use wildcards in method return types."

A friend of mine was writing some neural-net stuff in Java the other day. He
started out using methods that returned wildcard-generic types. The problem
with this becomes evident only after you start building lots of connected
structures off these return types. Of a sudden, you languish between the type
of one structure and the type of some other component that should, somehow,
match on their generic base types but you can't make them line up. They keep
having different "capture#k-of ?" numbers.

This happened to the OP, even though he was using an unbounded wildcard.

Putting the method into a generic class got my friend out of his programming
quagmire. This thread and its clones have seen one generic-method approach:

public static <T> List <List <T>> build( T ... inputs )

Joshua Bloch, /Effective Java/, Item 28: "Use bounded wildcards to increase
API flexibility":
*Do not use wildcard types as return types.* [emphasis original]
Rather than providing additional flexibility for your users,
it would force them to use wildcard types in client code.

Brian Goetz, "Java theory and practice: Going wild with generics, Part 2 (The
get-put principle)", IBM developerWorks®,
*Keep bounded wildcards out of return values* [header bold original]

It is sometimes tempting to use a bounded wildcard in the return type
of a method. But this temptation is best avoided because returning
bounded wildcards tends to "pollute" client code. If a method were to
return a Box<? extends T>, then the type of the variable receiving the
return value would have to be Box<? extends T>, which pushes the burden
of dealing with bounded wildcards on your callers. Bounded wildcards
work best when they are used in APIs, not in client code.
 
L

Lew

grz01 said:
My own firm opinion is that you are *grossly*
underestimating the "limited benefit".

I think Sun might need more than one programmer's opinion on the benefit to a
new API call, much less a Java language change. I'll get back to this point
in a moment.
If you are programming Java,
and you seriously think about it,
I am actually sure you have already suffered
many times yourself from this missing feature,
without even realizing it.

Ooh! Ow! Ouch! Oh, my! I'm suffering, man, I am suffering!

All joking aside, you are focusing on the marginal cost to the developers of
Java for one specific benefit. You might be aware that there's a Java
Community Process (JCP) for language changes. It works sort of like a
plebiscite, with additional voter responsibilities. It's pretty easy to
suggest language or API changes, even officially, much less passionately on
some random Usenet forum. What's difficult is to get enough traction with the
Java community at large - even closures to date have failed to achieve, ahem,
closure, and there is a very powerful minority in favor of that feature. (If
you care, I abstain on the closures issue.) That's a little unfair in that
closures are complex and there's a plethora of options. Two, to be exact, but
how many major Java proposals ever have more than one make it to the home stretch?

But what is fair is to realize that every proposal to change Java, even the
standard API, is driven by multiple factors - the degree of utility of the
proposed feature times how widespread its applicability, the complexity or
cost times the entire size of the Java community past and present, popularity
of the suggestion, and a prediction of how much such the change will paint the
feature set into a corner come future. This has to be weighed against every
other proposal - proposed changes don't occur in a vacuum but in a world where
everyone is suggesting all kinds of changes. Factor in that the labor force
to achieve these changes is limited and comprises mostly those voters who
champion the change.

Now shut up and write your own Pair<A, B> already. You can even copy and
paste the code this thread has given you - you've expended far more effort
complaining that it wasn't already done for you than you would have using the
code that was, in fact, already done for you.
 
G

grz01

First of all, maybe you should reconsider your choice of language.
I don't think there will ever be a programming language that is really
good for all styles of programming. It is much easier to write
functional language style code in a functional language than in Java.

Hi Patricia!

Sure. Would be nice of course, if you could always chose your own
coding language...

.... and still make a good living out of it! :)

From my experience, though, if you like to make an income from your
efforts, while also having a reasonably large base of interesting
projects and customer to chose between, I think there are quite few
sensible choices of language today. In fact, only two comes to mind:
C# or Java.

As to functional programming style and Java, though... my style of
programming in Java (or any other language I use, for that matter) I
would say, is still heavily influenced from my background in
functional languages. And I am still very pleased with the skills I
gained during that period, even if it was many many years ago now.

Thanks for your code-example -- will check it out!

/ grz01
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top