johnmmcparland said:
I suppose the problem I'm trying to acheive here is having a Vector
which could store Strings or could store Integers. I know I will only
store one of the other but not sure which (depends on the calling
classes).
You can use a List (pick your own implementation) or Collection that
stores a common supertype of the two types, without wildcards.
Collection <Object> stuff = new ArrayList <Object> ();
A wildcard indicates a homogeneous collection, one that wouldn't be able to
hold both Strings and Integers, though it could hold Objects.
The point of generic types is to capture and enforce type decisions. This
Collection will only know that it holds Objects, so you don't have much
benefit of generics.
Since you indicate that your collection is homogeneous, you can use a wildcard
pegged to the common supertype, '? extends Object', or more succinctly, '?'.
Based on a flag or input or something, you instantiate the actual collection
type:
Collection <?> stuff = (isAlfa? new ArrayList <String> ()
: new ArrayList <Integer> ());
This buys you a slight, very slight generics advantage, but doesn't free you
of risky runtime casting.
You get full benefit if you use a generic method or class to handle the logic,
separating the input format from its processing polymorphically and generically.
This slightly long example should convey the main idea, that generics plus
polymorphism equals object-oriented type safety. The class 'ScreenHandler'
fakes out how it might handle received data differently for String or Integer.
The nested classes simulate the isolation between screen input and typed
handling by the logic. Notice in particular the ScreenHandler main() and
handle() methods near the bottom. This is an SSCCE - the output is shown at
the bottom.
<sscce class="testit.ScreenHandler" >
/* ScreenHandler */
package testit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/** ScreenHandler. */
public class ScreenHandler
{
public static class ScreenData
{
private static final String [] ALFAS = { "1", "2", "3" };
public Collection <Object> getData()
{
return Arrays.asList( (Object []) ALFAS );
}
}
public static interface Handler <T>
{
public void gather( ScreenData data );
public void act();
}
public static class AlfaHandler implements Handler <String>
{
private Collection <String> stuff = new ArrayList <String> ();
@Override public void gather( ScreenData data )
{
for ( Object datum : data.getData() )
{
stuff.add( datum.toString() );
}
}
@Override public void act()
{
System.out.print( "ALFA: { " );
for ( String thing : stuff )
{
System.out.print( "\"" );
System.out.print( thing );
System.out.print( "\", " );
}
System.out.println( "}" );
}
}
public static class NumaHandler implements Handler <Integer>
{
private Collection <Integer> stuff = new ArrayList <Integer> ();
@Override public void gather( ScreenData data )
{
for ( Object datum : data.getData() )
{
try
{
stuff.add( Integer.valueOf( datum.toString() ));
}
catch ( NumberFormatException exc )
{
stuff.add( Integer.valueOf( 0 ));
}
}
}
@Override public void act()
{
System.out.print( "NUMA: { " );
for ( Integer thing : stuff )
{
System.out.print( thing );
System.out.print( ", " );
}
System.out.println( "}" );
}
}
private boolean alfa;
public final boolean isAlfa()
{
return this.alfa;
}
public final void setAlfa( boolean value )
{
this.alfa = value;
}
public void handle( ScreenData data )
{
Handler <?> handler =
(isAlfa()? new AlfaHandler() : new NumaHandler());
handler.gather( data );
handler.act();
}
public static void main( String [] args )
{
ScreenData screen = new ScreenData();
ScreenHandler handler = new ScreenHandler();
handler.setAlfa( false );
handler.handle( screen );
handler.setAlfa( true );
handler.handle( screen );
}
}
</sscce>
Output:
NUMA: { 1, 2, 3, }
ALFA: { "1", "2", "3", }