Generics

T

Todd

Hello,

I have been reading about generics to determine if there is a way to
accomplish what I _assumed_ could be done. From what I can tell, what
I would like to do is not possible, but, honestly, generics are
confusing to me.

What I would like to do is have one method, say getValue(), that
returns each member of a mixed collection in its correct type. I have
determined the the object type when storing it into the map, so it is
available to me for use in the getValue() method. I thought that
something along the lines of

public <T> T getValue()
{
return ObjectType.cast( value );
}

would work. However, I am having no luck coming up with anything that
compiles, let alone runs, to return typed objects at runtime using a
single method.

I have searched through the group, but have not found anything that
clarifies for me whether this concept can be implemented.

Is there a way to return typed objects from a mixed collection at
runtime using a single method? If so, could you provide me some tips
as to how to create the method or class with method to do so?

Thanks in advance,
Todd
 
D

Daniel Pitts

Todd said:
Hello,

I have been reading about generics to determine if there is a way to
accomplish what I _assumed_ could be done. From what I can tell, what
I would like to do is not possible, but, honestly, generics are
confusing to me.

What I would like to do is have one method, say getValue(), that
returns each member of a mixed collection in its correct type. I have
determined the the object type when storing it into the map, so it is
available to me for use in the getValue() method. I thought that
something along the lines of

public <T> T getValue()
{
return ObjectType.cast( value );
}

would work. However, I am having no luck coming up with anything that
compiles, let alone runs, to return typed objects at runtime using a
single method.

I have searched through the group, but have not found anything that
clarifies for me whether this concept can be implemented.

Is there a way to return typed objects from a mixed collection at
runtime using a single method? If so, could you provide me some tips
as to how to create the method or class with method to do so?

Thanks in advance,
Todd
Generics are determined either by the caller, or by the instantiater,
not by the returner.
Now, if did this:

public <T> T getValueAs(Class<T> type) {
return type.cast(value);
}

you might have better luck.


Or, better off:

class MyRef<T> {
T value;
public MyClass() {
}


public void setValue(T value) {
this.value = value;
}

public T getValue() {
return value;
}
}

MyRef<String> string = new MyRef<String>();
string.setValue("Hello!");

assert string.getValue().equals("Hello!");

What is it exactly that you are trying to do? I mean, what feature are
you adding that needs this?
 
T

Todd

Generics are determined either by the caller, or by the instantiater,
not by the returner.
Now, if did this:

public <T> T getValueAs(Class<T> type) {
return type.cast(value);

}

you might have better luck.

Or, better off:

class MyRef<T> {
T value;
public MyClass() {
}

public void setValue(T value) {
this.value = value;
}

public T getValue() {
return value;
}

}

MyRef<String> string = new MyRef<String>();
string.setValue("Hello!");

assert string.getValue().equals("Hello!");

What is it exactly that you are trying to do? I mean, what feature are
you adding that needs this?

I am reading a data file that contains a mix of doubles, double
arrays, integers, integer arrays, booleans and strings. Each entry
has a name (its key) and value associated with it. I know that when I
request "NumEntries" that the return will be an integer, so I thought
I would code something like

Integer numEntries = getValue( "NumEntries" );

and have an integer return. Further example, knowing "Description"
contains a string I would code something like

String description = getValue( "Description" );
 
C

Christian

Todd said:
I am reading a data file that contains a mix of doubles, double
arrays, integers, integer arrays, booleans and strings. Each entry
has a name (its key) and value associated with it. I know that when I
request "NumEntries" that the return will be an integer, so I thought
I would code something like

Integer numEntries = getValue( "NumEntries" );

and have an integer return. Further example, knowing "Description"
contains a string I would code something like

String description = getValue( "Description" );

Sometimes you are better off without using generics.
it might be better to use something like:

String getValue(String key) {}
int getIntValue(String key) {}

and not use generics for this.

Christian
 
T

Todd

Exactly how?

All,

Here is the source that I came up with to do this. Please critique
it. I would like to have concrete comments as to how it could be
improved For example, I read a TechTip that said it would be better
to use a scanner or at least String.split() in lieu of the
StringTokenizer.

Todd


//=========================================


import java.util.StringTokenizer;
import java.util.Vector;

/**
*
* @author heidenthal
*/
public class DataRecord
{
public DataRecord( String value, String description )
{
// Fill the data record with the passed information
this.value = new String( value );
this.description = new String( description );

// The record value needs to have its data type defined
// for the typed return of the value
dataType = determineType( value );
}

public String getDescription()
{
return description;
}

public <T> T getValue()
{
@SuppressWarnings( "unchecked" ) // TODO check cast and don't
suppress
Class <T> type = dataType.getClassType();

return type.cast( dataType.castValue( value ) );
}

public Class getClassType()
{
return dataType.getClassType();
}

private DataType determineType( String value )
{
dataType = DataType.STRING;

// boolean type
if( isBoolean( value ) )
{
dataType = DataType.BOOLEAN;
}
else if( isInteger( value ) ) // int type
{
dataType = DataType.INTEGER;
}
else if( isDouble( value ) ) // double type
{
dataType = DataType.DOUBLE;
}
else if( isDoubleArray( value ) ) // double[] type
{
dataType = DataType.DOUBLE_ARRAY;
}

return dataType;
}

private boolean isBoolean( String value )
{
if( value.equalsIgnoreCase( "true" ) ||
value.equalsIgnoreCase( "false" ) )
{
return true;
}

return false;
}

private boolean isInteger( String value )
{
try
{
Integer.parseInt( value );
return true;
}
catch( Exception exception )
{
return false;
}
}

private boolean isDouble( String value )
{
try
{
Double.parseDouble( value );
return true;
}
catch( Exception exception )
{
return false;
}
}

private boolean isDoubleArray( String value )
{
if( value.contains( "{" ) && value.contains( "}" ) )
{
return true;
}

return false;
}


private String value;
private String description;
private DataType dataType;


@SuppressWarnings( "unchecked" ) // TODO check cast and don't
suppress
private enum DataType
{
STRING( String.class )
{
String castValue( String value )
{
return value;
}
},

BOOLEAN( Boolean.class )
{
Boolean castValue( String value )
{
return Boolean.parseBoolean( value );
}
},

INTEGER( Integer.class )
{
Integer castValue( String value )
{
return Integer.parseInt( value );
}
},

DOUBLE( Double.class )
{
Double castValue( String value )
{
return Double.parseDouble( value );
}
},

DOUBLE_ARRAY( Double[].class )
{
Double[] castValue( String value )
{
Vector<Double> values = new Vector<Double>();

StringTokenizer tokenizer =
new StringTokenizer( value.substring( 1 ),
" }" );
while( tokenizer.hasMoreTokens() )
{

values.add( Double.parseDouble( tokenizer.nextToken() ) );
}

Double[] valuesArray = new Double[values.size()];
valuesArray = values.toArray( valuesArray );

return valuesArray;
}
};

DataType( Class clazz )
{
this.clazz = clazz;
}

abstract <T> T castValue( String value );

Class getClassType()
{
return clazz;
}


private Class clazz;
}
}

//========================================


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Locale;
import java.util.StringTokenizer;

/**
*
* @author heidenthal
*/
public class DataCollection extends HashMap<String, DataRecord>
{
public DataCollection( String filename )
{
buildDefaultMap( filename );
}

public void buildDefaultMap( String filename )
{
String line = null;
InputStream reader =
Class.class.getResourceAsStream( filename );
try
{
BufferedReader bufferedReader =
new BufferedReader( new
InputStreamReader( reader ) );
while( (line = bufferedReader.readLine()) != null )
{
// Break the line into the key and data record
StringTokenizer str = new StringTokenizer( line,"=" );

// Get the key for the data
String key =
str.nextToken().trim().toUpperCase(Locale.ENGLISH);

// Get the record value
String value = str.nextToken( "=," ).trim();

// Get the description (if it exists)
String description = str.nextToken( "\n" ).trim();

// Create a new data record and add it to the
collection
DataRecord dataRecord = new DataRecord( value,
description );

this.put( key, dataRecord );
}
}
catch( IOException ioException )
{
System.err.println( "Unable to open " + filename );
System.err.println( ioException );
}
}

public <T> T get( String key ) throws NullPointerException
{
DataRecord dataRecord =
super.get( key.trim().toUpperCase(Locale.ENGLISH) );

@SuppressWarnings( "unchecked" ) // TODO check cast and don't
suppress
Class<T> type = dataRecord.getClassType();

return type.cast( dataRecord.getValue() );
}
}
 
L

Lew

Todd said:
import java.util.StringTokenizer;
import java.util.Vector;

Don't use java.util.Vector. Use one of the List implementations that replaced
it in 1998, such as ArrayList.
public <T> T getValue()
{
@SuppressWarnings( "unchecked" ) // TODO check cast and don't
suppress
Class <T> type = dataType.getClassType();

The need for an "unchecked" suppression is an indicator that you don't have
the generics quite right. Don't feel bad; with type erasure it isn't easy to
get generics exactly right, warning-free.
 
T

Todd

Don't use java.util.Vector. Use one of the List implementations that replaced
it in 1998, such as ArrayList.


The need for an "unchecked" suppression is an indicator that you don't have
the generics quite right. Don't feel bad; with type erasure it isn't easy to
get generics exactly right, warning-free.

Lew,

Question about ArrayList vs. Vector. I remember reading that one
should only use Vector since it is the only collection _guaranteed_ to
be thread-safe. Is this no longer considered true?

Todd
 
O

Owen Jacobson

Don't use java.util.Vector.  Use one of the List implementations that replaced
it in 1998, such as ArrayList.
The need for an "unchecked" suppression is an indicator that you don't have
the generics quite right.  Don't feel bad; with type erasure it isn't easy to
get generics exactly right, warning-free.

Please don't quote signatures.
Lew,

Question about ArrayList vs. Vector.  I remember reading that one
should only use Vector since it is the only collection _guaranteed_ to
be thread-safe.  Is this no longer considered true?

It depends on what you mean by "thread-safe". All of Vector's methods
are declared synchronized, which means that only one method may be in
progress on a single Vector at a time. However, this provides no
guarantees about coherency across multiple method calls, nor
particularly across iteration.

If you need the same promise from a List, you can use
Collections.synchronizedList (backingList) to construct a wrapper
around a List that performs the same synchronization that Vector
does. However, I've rarely found synchronizing on individual lists to
be all that useful, for the reasons I outlined above.

-o
 
M

Mark Space

Todd said:
Question about ArrayList vs. Vector. I remember reading that one
should only use Vector since it is the only collection _guaranteed_ to
be thread-safe. Is this no longer considered true?

As Owen said, this is totally untrue. Vectors are required to be thread
safe, thus requiring synchronization overhead whether you need it or
not. All other (new) collections have a separate thread-safe version
that you can instantiate optionally if you want thread safety.

Where the heck did you read this drivel? Seriously, I'm interested in
knowing who is promulgating nonsense about Java.

Thanks in advance.
 
L

Lew

Todd said:
Question about ArrayList vs. Vector. I remember reading that one
should only use Vector since it is the only collection _guaranteed_ to
be thread-safe. Is this no longer considered true?

It was never true, whether some considered it so or not. The rule prior to
1998 was only to use Vector because it was the only choice. After that, it
was to use ArrayList unless you needed or wanted the collection to be
inherently synchronized. Most of the time you don't need thread safety
because the context is not multi-threaded. So most of the time, the built-in
overhead of Vector's synchronization (much less in modern JVMs) was wasted
overhead.

It remains true since 1998 that if you do want or need to use synchronization
on your List, then Vector is the wrong choice. The right choice is at least
Collections.synchronizedList( someList ).
<http://java.sun.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)>

More sophisticated concurrent algorithms can use the java.util.concurrent
package and its kin.
<http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html>
 
A

Andreas Leitgeb

Mark Space said:
As Owen said, this is totally untrue. Vectors are required to be thread
safe, thus requiring synchronization overhead whether you need it or
not. All other (new) collections have a separate thread-safe version
that you can instantiate optionally if you want thread safety.

It was partially untrue, in that Vector is not the only one. But anyway it
is the only one where you have thread-safety concisely, without the extra
boilerplate of Collections.synchronizedWhatever(...).

PS1: If Thread-safety is not an requirement, then Vector is of course
unnecessarily slower than other Collections.

PS2: If I need to deal with the capacity of a synchronized array-like
Collection, how would I do this with ArrayList and
Collections.synchronized*What* ?
 
R

RedGrittyBrick

Andreas said:
PS1: If Thread-safety is not an requirement, then Vector is of ...
PS2: If I need to deal with the capacity of a synchronized ...

PS1: Sony PlayStation.
PS2: Sony PlayStation 2.

For postscripts I prefer the traditional abbreviations:

PS
PPS

and so on.
 
L

Lew

Andreas said:
PS2: If I need to deal with the capacity of a synchronized array-like
Collection, how would I do this with ArrayList and
Collections.synchronized*What* ?

What do you mean, "to deal with the capacity of a ... Collection"?

For operations on a synchronized List, you use the returned List from the
Collections.synchronizedList() call.

List <T> synched = Collections.synchronizedList( unsynched );
...
synchronized( synched )
{
if ( synched.size() == 0 )
{
synched.add( foo );
}
}
etc.
 
A

Andreas Leitgeb

Lew said:
What do you mean, "to deal with the capacity of a ... Collection"?

I meant, I had a look at the Javadoc for ArrayList and skimmed over
those of its methods that aren't specified by interfaces. Only
those that deal with capacity (querying and setting) are specific
to ArrayList. Plus there is also removeRange(), which it inherits
from AbstractList, and thus also isn't available through List-API.
Vector also offers these features.

While I'm not judging the practical value of these, it seems like
Vector was the only threadsafe collection that had removeRange
and a means to get/set the capacity in case a known large number
of items needs to be added, to avoid multiple incremental
re-allocations.
 
L

Lew

Andreas said:
I meant, I had a look at the Javadoc for ArrayList and skimmed over
those of its methods that aren't specified by interfaces. Only
those that deal with capacity (querying and setting) are specific

Well, setting, anyway.
to ArrayList. Plus there is also removeRange(), which it inherits
from AbstractList, and thus also isn't available through List-API.
Vector also offers these features.

While I'm not judging the practical value of these, it seems like
Vector was the only threadsafe collection that had removeRange
and a means to get/set the capacity in case a known large number
of items needs to be added, to avoid multiple incremental
re-allocations.

Why do people insist on calling Vector "thread safe"? Having synchronized
methods doesn't make it thread safe.

If you set the capacity then add items, you need to explicitly synchronize on
the Vector anyway. Individual methods' synchronization doesn't extend through
multiple method calls. There's no advantage to Vector here.

It also happens that removeRange() is a protected method, so relying on it
forces you to extend AbstractList or a subclass. This is extra work that,
from what you've indicated, doesn't solve your synchronization problem. Plus
now you have to maintain an extra class instead of simply relying on the Java
API. Work you'd avoid by using ArrayList and synchronizing explicitly, since
you have to anyway.

I'd just use an ArrayList variable (for the extra methods List doesn't
support), and explicitly synchronize.
 
L

Lew

What's wrong with multiple re-allocations? AIUI, ArrayList grows its capacity
by doubling the array size, so there's not going to be a whole lot of
re-allocation overhead - possibly even less than by manually calling
ensureCapacity(), if you're not at least doubling the internal capacity with
each call.
 
P

Patricia Shanahan

Andreas said:
I meant, I had a look at the Javadoc for ArrayList and skimmed over
those of its methods that aren't specified by interfaces. Only
those that deal with capacity (querying and setting) are specific
to ArrayList. Plus there is also removeRange(), which it inherits
from AbstractList, and thus also isn't available through List-API.
Vector also offers these features.

While I'm not judging the practical value of these, it seems like
Vector was the only threadsafe collection that had removeRange
and a means to get/set the capacity in case a known large number
of items needs to be added, to avoid multiple incremental
re-allocations.

removeRange is not really needed, because the same job can be done using
only the List interface: myList.subList(from, to).clear();

This sort of operation requires explicit synchronization to prevent any
changes in the list between calculation of the index values and the
clear call.

Patricia
 
A

Andreas Leitgeb

Lew said:
Why do people insist on calling Vector "thread safe"? Having synchronized
methods doesn't make it thread safe.

I fail to see in which way a Vector was any *less* "thread safe" than
a Collections.synchronizedList(new ArrayList(...)).

Docu for synchronizedList says:
" Returns a synchronized (thread-safe) ..."
Note, it doesn't say "synchronized and also thread-safe",
but rather seems to consider those two to be like synonyms.

Docu for Vector only says:
" Vector is synchronized.

What operations can I do on a synchronizedList without extra
synchronization-block, that I cannot do on a Vector likewise
and with same level of real thread-safety?
 

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

generics puzzle 57
Google sheets 2
can this be done with generics? 32
Generics Amanuensis? 2
Google sheets 0
Generics and Polymorphism 5
More Generics warnings. 5
Generics Issue 13

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top