Using Enumerated Types as Array Indexes

Discussion in 'Java' started by KevinSimonson, Aug 16, 2011.

  1. Ada, the programming language mandated for the military for a time,
    was a wonderful language that didn't deserve to die. But it did, and
    now Java is alive and well and nobody seems to be doing anything at
    all with Ada.

    Java is a pretty handy language in its own right. But in Ada one
    could define arrays to be indexed by enumerated types. Can Java do
    that? If not, why not?

    I wrote a piece of code that implements an array of <String>s, indexed
    by objects of class <Coord>, an enumerated type, that I'm including
    below. Obviously the functionality of this class could be copied to
    make it possible to create _virtual_ arrays of _any_ element class,
    indexed by _any_ enumerated type. Isn't this precisely the thing
    generics were designed for? But how does one write a generic class to
    implement an array indexed by enumerated types?

    I've also included below three attempts to create a generic type that
    implements an array indexed by enumerated types, but none of them
    compile. Can anyone give me some pointers on this?

    Kevin Simonson



    Script started on Tue Aug 16 06:47:31 2011
    sh-4.1$ ls
    ArrayEnum.class Coord.class EnumArray2.java Offsetable.java
    ArrayEnum.java EnumArray1.java EnumArray3.java
    sh-4.1$ : First the Java file that _does_ work.
    sh-4.1$ cat ArrayEnum.java
    enum Coord { X_LFT, Y_LFT, X_RHT, Y_RHT }

    public class ArrayEnum
    {
    String[] arrEnm;

    public ArrayEnum ()
    {
    arrEnm = new String[ Coord.values().length];
    }

    public void set ( Coord index
    , String element)
    {
    arrEnm[ index.ordinal()] = element;
    }

    public String get ( Coord index)
    {
    return arrEnm[ index.ordinal()];
    }

    public static void main ( String[] arguments)
    {
    if (0 < arguments.length && arguments.length % 2 == 0)
    { ArrayEnum demo = new ArrayEnum();
    Coord[] allCoords = Coord.values();
    Coord chosen;
    int index;
    for (Coord enm : Coord.values())
    { demo.set( enm, enm + "_orig_value");
    }
    System.out.println( "Before setting values:");
    for (Coord enm : Coord.values())
    { System.out.println
    ( "demo.get( " + enm + ") == \"" + demo.get( enm) + "\".");
    }
    for (int arg = 0; arg < arguments.length; arg += 2)
    { index = -1;
    for (;;)
    { if (++index == allCoords.length)
    { chosen = null;
    break;
    }
    if (arguments[ arg].toUpperCase().equals( "" +
    allCoords[ index]))
    { chosen = allCoords[ index];
    break;
    }
    }
    if (chosen != null)
    { System.out.println
    ( "demo.set( " + chosen + ", \"" + arguments[ arg + 1] +
    ");");
    demo.set( chosen, arguments[ arg + 1]);
    }
    else
    { System.out.println
    ( "Couldn't match argument \"" + arguments[ arg]
    + "\" with a <Coord>
    value!");
    }
    }
    System.out.println( "After setting values:");
    for (Coord enm : Coord.values())
    { System.out.println
    ( "demo.get( " + enm + ") == \"" + demo.get( enm) + "\".");
    }
    }
    else
    { System.out.println( "Usage is");
    System.out.println( " java ArrayEnum (<coord> <accompanying-
    string>)+");
    }
    }
    }
    sh-4.1$ : I compile it.
    sh-4.1$ javac ArrayEnum.java
    sh-4.1$ : It compiles without error messages, so I run it with some
    values.
    sh-4.1$ java ArrayEnum x_rht Kevin x_lft Sandy y_rht Joshua
    Before setting values:
    demo.get( X_LFT) == "X_LFT_orig_value".
    demo.get( Y_LFT) == "Y_LFT_orig_value".
    demo.get( X_RHT) == "X_RHT_orig_value".
    demo.get( Y_RHT) == "Y_RHT_orig_value".
    demo.set( X_RHT, "Kevin);
    demo.set( X_LFT, "Sandy);
    demo.set( Y_RHT, "Joshua);
    After setting values:
    demo.get( X_LFT) == "Sandy".
    demo.get( Y_LFT) == "Y_LFT_orig_value".
    demo.get( X_RHT) == "Kevin".
    demo.get( Y_RHT) == "Joshua".
    sh-4.1$ : Then the three attempts at generic implementations, with the
    sh-4.1$ : compilation error messages that accompanied them.
    sh-4.1$ cat EnumArray1.java
    import java.util.Iterator;

    public class EnumArray1< Ty, En extends Enum< En>> implements Iterator
    {
    Ty[] enumArray;
    En nextToRead;

    public EnumArray1 ()
    {
    En[] vlues = En.values();
    enumArray = new Ty[ vlues.length];
    nextToRead = 0 < vlues.length ? vlues[ 0] : null;
    }

    public Ty get ( En index)
    {
    return enumArray[ index.ordinal()];
    }

    public void set ( En index
    , Ty vlue)
    {
    enumArray[ index.ordinal()] = vlue;
    }

    public int size ()
    {
    return enumArray.length;
    }

    public boolean last ( En enm)
    {
    return enm.ordinal() + 1 == enumArray.length;
    }

    public boolean first ( En enm)
    {
    return enm.ordinal() == 0;
    }

    public En succ ( En enm)
    {
    int index = enm.ordinal() + 1;
    return index < enumArray.length ? En.values()[ index] : null;
    }

    public En pred ( En enm)
    {
    int index = enm.ordinal() - 1;
    return 0 <= index ? En.values()[ index] : null;
    }

    public boolean hasNext()
    {
    return nextToRead != null;
    }

    public Object next ()
    {
    Object nxtEnm = (Object) nextToRead;
    nextToRead = next( nextToRead);
    return nxtEnm;
    }

    public void remove ()
    {
    }
    }
    sh-4.1$ javac EnumArray1.java
    EnumArray1.java:10: cannot find symbol
    symbol : method values()
    location: class java.lang.Enum<En>
    En[] vlues = En.values();
    ^
    EnumArray1.java:11: generic array creation
    enumArray = new Ty[ vlues.length];
    ^
    EnumArray1.java:44: cannot find symbol
    symbol : method values()
    location: class java.lang.Enum<En>
    return index < enumArray.length ? En.values()[ index] : null;
    ^
    EnumArray1.java:50: cannot find symbol
    symbol : method values()
    location: class java.lang.Enum<En>
    return 0 <= index ? En.values()[ index] : null;
    ^
    EnumArray1.java:61: next() in EnumArray1<Ty,En> cannot be applied to
    (En)
    nextToRead = next( nextToRead);
    ^
    5 errors
    sh-4.1$ cat EnumArray2.java
    import java.util.Iterator;

    public class EnumArray2< Ty, En extends Enum< En>> implements Iterator
    {
    Object[] enumArray;
    En nextToRead;

    public EnumArray2 ()
    {
    En[] vlues = En.values();
    enumArray = new Object[ vlues.length];
    nextToRead = 0 < vlues.length ? vlues[ 0] : null;
    }

    public Ty get ( En index)
    {
    return (Ty) enumArray[ index.ordinal()];
    }

    public void set ( En index
    , Ty vlue)
    {
    enumArray[ index.ordinal()] = (Object) vlue;
    }

    public int size ()
    {
    return enumArray.length;
    }

    public boolean last ( En enm)
    {
    return enm.ordinal() + 1 == enumArray.length;
    }

    public boolean first ( En enm)
    {
    return enm.ordinal() == 0;
    }

    public En succ ( En enm)
    {
    int index = enm.ordinal() + 1;
    return index < enumArray.length ? En.values()[ index] : null;
    }

    public En pred ( En enm)
    {
    int index = enm.ordinal() - 1;
    return 0 <= index ? En.values()[ index] : null;
    }

    public boolean hasNext()
    {
    return nextToRead != null;
    }

    public Object next ()
    {
    Object nxtEnm = (Object) nextToRead;
    nextToRead = next( nextToRead);
    return nxtEnm;
    }

    public void remove ()
    {
    }
    }
    sh-4.1$ javac EnumArray2.java
    EnumArray2.java:10: cannot find symbol
    symbol : method values()
    location: class java.lang.Enum<En>
    En[] vlues = En.values();
    ^
    EnumArray2.java:44: cannot find symbol
    symbol : method values()
    location: class java.lang.Enum<En>
    return index < enumArray.length ? En.values()[ index] : null;
    ^
    EnumArray2.java:50: cannot find symbol
    symbol : method values()
    location: class java.lang.Enum<En>
    return 0 <= index ? En.values()[ index] : null;
    ^
    EnumArray2.java:61: next() in EnumArray2<Ty,En> cannot be applied to
    (En)
    nextToRead = next( nextToRead);
    ^
    Note: EnumArray2.java uses unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
    4 errors
    sh-4.1$ cat EnumArray3.java
    import java.util.Iterator;

    public class EnumArray3< Ty, En extends Offsetable, Enum> implements
    Iterator
    {
    private static class Associated
    {
    Offsetable value;
    Object element;

    Associated ( Offsetable enm)
    { value = enm;
    }
    }

    final En INIT_VALUE;
    Associated[] enumArray;
    En nextToRead;

    private void fillValues ( Offsetable enm
    , int index)
    {
    try
    { fillValues( enm.offsetBy( 1), index + 1);
    }
    catch (ArrayIndexOutOfBoundsException excptn)
    { enumArray = new Associated[ index + 1];
    }
    enumArray[ index] = new Associated( enm);
    }

    public EnumArray3 ( En initialValue)
    {
    INIT_VALUE = initialValue;
    nextToRead = initialValue;
    fillValues( (Offsetable) initialValue, 0);
    }

    public Ty get ( En index)
    {
    return (Ty) enumArray[ index.ordinal()].element;
    }

    public void set ( En index
    , Ty vlue)
    {
    enumArray[ index.ordinal()].element = (Object) vlue;
    }

    public int size ()
    {
    return enumArray.length;
    }

    public boolean last ( En enm)
    {
    return enm.ordinal() + 1 == enumArray.length;
    }

    public boolean first ( En enm)
    {
    return enm.ordinal() == 0;
    }

    public boolean hasNext()
    {
    return nextToRead != null;
    }

    public Object next ()
    {
    Object nxtEnm = (Object) nextToRead;
    nextToRead = nextToRead.offsetBy( 1);
    return nxtEnm;
    }

    public void remove ()
    {
    }
    }
    sh-4.1$ javac EnumArray3.java
    EnumArray3.java:40: cannot find symbol
    symbol : method ordinal()
    location: interface Offsetable
    return (Ty) enumArray[ index.ordinal()].element;
    ^
    EnumArray3.java:46: cannot find symbol
    symbol : method ordinal()
    location: interface Offsetable
    enumArray[ index.ordinal()].element = (Object) vlue;
    ^
    EnumArray3.java:56: cannot find symbol
    symbol : method ordinal()
    location: interface Offsetable
    return enm.ordinal() + 1 == enumArray.length;
    ^
    EnumArray3.java:56: operator + cannot be applied to
    Offsetable.ordinal,int
    return enm.ordinal() + 1 == enumArray.length;
    ^
    EnumArray3.java:56: incomparable types: <nulltype> and int
    return enm.ordinal() + 1 == enumArray.length;
    ^
    EnumArray3.java:61: cannot find symbol
    symbol : method ordinal()
    location: interface Offsetable
    return enm.ordinal() == 0;
    ^
    EnumArray3.java:72: incompatible types
    found : Offsetable
    required: En
    nextToRead = nextToRead.offsetBy( 1);
    ^
    Note: EnumArray3.java uses unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
    7 errors
    sh-4.1$ exit
    exit

    Script done on Tue Aug 16 06:50:57 2011
     
    KevinSimonson, Aug 16, 2011
    #1
    1. Advertising

  2. KevinSimonson

    Tom Anderson Guest

    On Tue, 16 Aug 2011, KevinSimonson wrote:

    > Java is a pretty handy language in its own right. But in Ada one could
    > define arrays to be indexed by enumerated types. Can Java do that?


    No.

    > If not, why not?


    Because in Java, arrays are indexed by integers, and values of enumerated
    types are objects (which are not integers).

    As Patricia has pointed out, there is EnumMap. And your code below is not
    too far off doing the same thing.

    > sh-4.1$ javac EnumArray1.java
    > EnumArray1.java:10: cannot find symbol
    > symbol : method values()
    > location: class java.lang.Enum<En>
    > En[] vlues = En.values();


    Every enum type has a static values() method, but you can't call static
    methods polymorphically like this. In fact, i don't think you can call
    static methods on type variables at all, although i could be wrong.

    However, the Class class does have a getEnumConstants() methods which does
    what you want. If the constructor takes a suitable instance of Class, it
    can use that method.

    > EnumArray1.java:11: generic array creation
    > enumArray = new Ty[ vlues.length];
    > ^


    An annoying consequence of Java's approach to generics (type erasure) is
    that you can't create arrays of a generic type. But if you have a Class
    object for the component type, you can use java.lang.reflect.Array's
    newInstance method to create one.

    > EnumArray1.java:61: next() in EnumArray1<Ty,En> cannot be applied to
    > (En)
    > nextToRead = next( nextToRead);
    > ^


    There is no single-argument method called next in your code.

    Here's an implementation of the constructor which might work (barring a
    bit of try-catch around the reflection):

    public EnumArray1(Class<En> type) {
    En[] values = type.getEnumConstants();
    enumArray = Array.newInstance(type, values.length);
    nextToRead = values[0];
    }

    I've dispensed with the length check, because if someone passes in an
    empty enum, then as far as i'm concerned, they deserve the
    ArrayIndexOutOfBoundsException they'll get.

    I haven't gone over your other classes, because hopefully this should
    solve all your problems.

    Note that the constructor i suggest is used like this:

    EnumArray1<RockPaperScissors> rps = new EnumArray1<RockPaperScissors>(RockPaperScissors.class);

    Which is a bit annoying. If you are very annoyed, and if you are prepared
    to stomach some reflective witchcraft, you can add another, more magical,
    constructor:

    protected EnumArray1() {
    this((Class<En>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    }

    Which lets you then write a more magical but briefer construction
    expression:

    EnumArray1<RockPaperScissors> rps = new EnumArray1<RockPaperScissors>() {};

    I would suggest, though, that you don't.

    tom

    --
    Freedom, Beauty, Truth, and Love!
     
    Tom Anderson, Aug 16, 2011
    #2
    1. Advertising

  3. On Tue, 16 Aug 2011 07:53:38 -0700 (PDT), KevinSimonson
    <> wrote:

    >Ada, the programming language mandated for the military for a time,
    >was a wonderful language that didn't deserve to die. But it did, and
    >now Java is alive and well and nobody seems to be doing anything at
    >all with Ada.
    >
    >Java is a pretty handy language in its own right. But in Ada one
    >could define arrays to be indexed by enumerated types. Can Java do
    >that? If not, why not?


    I do not know if this is relevant for you, but C# apparently can.
    It involves redefinition of []. I coded a simple case of "one",
    "two", and "three" each setting/getting the respective array element
    and anything else getting/getting element 0. I assume that an enum
    value would work, too.

    [snip]

    Sincerely,

    Gene Wirchenko
     
    Gene Wirchenko, Aug 16, 2011
    #3
  4. KevinSimonson

    Arne Vajhøj Guest

    On 8/16/2011 10:53 AM, KevinSimonson wrote:
    > Ada, the programming language mandated for the military for a time,
    > was a wonderful language that didn't deserve to die. But it did, and
    > now Java is alive and well and nobody seems to be doing anything at
    > all with Ada.
    >
    > Java is a pretty handy language in its own right. But in Ada one
    > could define arrays to be indexed by enumerated types. Can Java do
    > that? If not, why not?


    Java is a simpler language than Ada. In Java array indexes are
    int and you have byte/short/int/long types and that is it.

    You will need to either use values 0..n-1 as array indexes or
    switch to one of the Map data types in java.util.

    Arne
     
    Arne Vajhøj, Aug 17, 2011
    #4
  5. KevinSimonson

    Arne Vajhøj Guest

    On 8/16/2011 5:54 PM, Gene Wirchenko wrote:
    > On Tue, 16 Aug 2011 07:53:38 -0700 (PDT), KevinSimonson
    > <> wrote:
    >> Ada, the programming language mandated for the military for a time,
    >> was a wonderful language that didn't deserve to die. But it did, and
    >> now Java is alive and well and nobody seems to be doing anything at
    >> all with Ada.
    >>
    >> Java is a pretty handy language in its own right. But in Ada one
    >> could define arrays to be indexed by enumerated types. Can Java do
    >> that? If not, why not?

    >
    > I do not know if this is relevant for you, but C# apparently can.
    > It involves redefinition of []. I coded a simple case of "one",
    > "two", and "three" each setting/getting the respective array element
    > and anything else getting/getting element 0. I assume that an enum
    > value would work, too.


    [] in C# can be either array index or using a so called
    indexer of a class.

    But it is either one or the other or not defined - it is
    never redefined.

    Arne
     
    Arne Vajhøj, Aug 17, 2011
    #5
  6. KevinSimonson

    Arne Vajhøj Guest

    On 8/16/2011 8:52 PM, markspace wrote:
    > On 8/16/2011 5:38 PM, Arne Vajhøj wrote:
    >> Java is a simpler language than Ada. In Java array indexes are
    >> int and you have byte/short/int/long types and that is it.

    >
    > Er, all primitives. I.e., add char/float/double and references to that.


    Sorry.

    byte/short/int/long integer types

    Point being that you don't have 1900..2011 and similar.

    Arne
     
    Arne Vajhøj, Aug 17, 2011
    #6
  7. KevinSimonson

    markspace Guest

    On 8/16/2011 6:56 PM, Arne Vajhøj wrote:
    > byte/short/int/long integer types


    OK, you mean for indexes? char works too, and long really doesn't -- it
    has to be cast to an int. For longs, Java recognizes the loss of
    precision using long and requires that you acknowledge that the upper
    bits will simply be truncated.
     
    markspace, Aug 17, 2011
    #7
  8. KevinSimonson

    Lew Guest

    On Tuesday, August 16, 2011 8:20:05 PM UTC-7, markspace wrote:
    > On 8/16/2011 6:56 PM, Arne Vajh�j wrote:
    > > byte/short/int/long integer types

    >
    > OK, you mean for indexes? char works too, and long really doesn't -- it
    > has to be cast to an int. For longs, Java recognizes the loss of
    > precision using long and requires that you acknowledge that the upper
    > bits will simply be truncated.


    JLS 10:
    "The variables contained in an array have no names; instead they are referenced by array access expressions that use nonnegative integer index values."

    IOW, you never index arrays with a byte, char or short. If you try, you get a widening conversion first, and if that results in a negative int value,you got problems.

    --
    Lew
     
    Lew, Aug 17, 2011
    #8
  9. KevinSimonson wrote:
    > Ada, the programming language mandated for the military for a time,
    > was a wonderful language that didn't deserve to die. But it did,


    No it didn't. The Ada language has been extended and updated regularly;
    a new standard is due to appear in 2012. Several compilers are
    available, one of the best being gnat, which is a part of gcc and is
    freely available on many platforms. See libre.adacore.com and
    http://en.wikipedia.org/wiki/Ada_(programming_language).

    > and now Java is alive and well


    Agreed.

    > and nobody seems to be doing anything at all with Ada.


    The number of people working with Ada is certainly smaller than for
    Java, but far from zero. Even the USENET group comp.lang.ada is quite
    active.

    --
    Niklas Holsti
    Tidorum Ltd
    niklas holsti tidorum fi
    . @ .
     
    Niklas Holsti, Aug 17, 2011
    #9
  10. On 11-08-17 12:45 AM, Lew wrote:
    > On Tuesday, August 16, 2011 8:20:05 PM UTC-7, markspace wrote:
    >> On 8/16/2011 6:56 PM, Arne Vajh�j wrote:
    >>> byte/short/int/long integer types

    >>
    >> OK, you mean for indexes? char works too, and long really doesn't -- it
    >> has to be cast to an int. For longs, Java recognizes the loss of
    >> precision using long and requires that you acknowledge that the upper
    >> bits will simply be truncated.

    >
    > JLS 10:
    > "The variables contained in an array have no names; instead they are referenced by array access expressions that use nonnegative integer index values."
    >
    > IOW, you never index arrays with a byte, char or short. If you try, you get a widening conversion first, and if that results in a negative int value, you got problems.
    >

    I'm feeling slow this morning: how do we get problems with byte->int,
    short->int, or char->int again? These are all integral widening
    primitive conversions, respectively

    byte->int: 8-bit signed 2's complement (2C) -> 32-bit signed 2C,
    short->int: 16-bit signed 2C -> 32-bit signed 2C
    char->int: 16-bit unsigned -> 32-bit signed 2C

    According to common sense and the JLS, all three of these conversions
    _exactly_ preserve the original value. How could they not?

    AHS
     
    Arved Sandstrom, Aug 17, 2011
    #10
  11. KevinSimonson

    David Lamb Guest

    On 16/08/2011 8:38 PM, Arne Vajhøj wrote:
    > On 8/16/2011 10:53 AM, KevinSimonson wrote:
    >> Java is a pretty handy language in its own right. But in Ada one
    >> could define arrays to be indexed by enumerated types. Can Java do
    >> that? If not, why not?

    >
    > Java is a simpler language than Ada. In Java array indexes are
    > int and you have byte/short/int/long types and that is it.


    Sure -- but if Enums had been in the language from the beginning, then
    it might have occurred to people that array indexes could be "any type
    with a method 'int ordinal()'" (with the appropriate caveat about being
    in range 0..length-1)
     
    David Lamb, Aug 17, 2011
    #11
  12. Arved Sandstrom <> wrote:
    > On 11-08-17 12:45 AM, Lew wrote:
    >> On Tuesday, August 16, 2011 8:20:05 PM UTC-7, markspace wrote:
    >>> On 8/16/2011 6:56 PM, Arne Vajh�j wrote:
    >>>> byte/short/int/long integer types
    >>> OK, you mean for indexes? char works too, and long really doesn't -- it
    >>> has to be cast to an int. [...]

    >> JLS 10: [...]
    >> IOW, you never index arrays with a byte, char or short. [...]

    > I'm feeling slow this morning: how do we get problems with byte->int,
    > short->int, or char->int again?


    array-indexing takes integers. That you can also throw byte/short/char
    values at them without cast doesn't mean that arrays "take" those, but
    only that such values get automatically converted to int before being
    taken by the array for indexing.

    An example for something really "taking" byte-values:
    foo(byte b) { ... }
     
    Andreas Leitgeb, Aug 17, 2011
    #12
  13. On 17.08.2011 14:29, David Lamb wrote:
    > On 16/08/2011 8:38 PM, Arne Vajhøj wrote:
    >> On 8/16/2011 10:53 AM, KevinSimonson wrote:
    >>> Java is a pretty handy language in its own right. But in Ada one
    >>> could define arrays to be indexed by enumerated types. Can Java do
    >>> that? If not, why not?

    >>
    >> Java is a simpler language than Ada. In Java array indexes are
    >> int and you have byte/short/int/long types and that is it.

    >
    > Sure -- but if Enums had been in the language from the beginning, then
    > it might have occurred to people that array indexes could be "any type
    > with a method 'int ordinal()'" (with the appropriate caveat about being
    > in range 0..length-1)


    Or we had an interface Countable { int ordinal(); } which Enum would
    implement and which could be used for array indexing. Or... I don't
    find it worthwhile to speculate about what could have happened if
    something else happened.

    And please also notice that there is still EnumMap as Patricia pointed
    out - type safe, efficient and all. Just because Ada does it this way
    doesn't mean that it's the best way or that other languages must follow
    suit.

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Aug 17, 2011
    #13
  14. KevinSimonson

    Lew Guest

    Andreas Leitgeb wrote:
    > Arved Sandstrom <> wrote:
    >> Lew wrote:
    >>> JLS 10: [...]
    >>> IOW, you never index arrays with a byte, char or short. [...]

    >> I'm feeling slow this morning: how do we get problems with byte->int,
    >> short->int, or char->int again?


    One gets problems with byte->int and short->int with array indexes the way one gets into trouble with those widening conversions generally. The usualsuspect is the lack of unsigned versions, so widening a (byte)0xA0, for example, would result in a negative index.

    One gets into trouble generally in programming when one thinks one thing isgoing on ("index takes a byte") whilst ignoring what's really going on (there's a widening conversion involved). You might get away with it most of the time, but occasionally such things trip you up.

    Why think about it imprecisely? Tell us the advantage of that, please.

    > array-indexing takes integers. That you can also throw byte/short/char
    > values at them without cast doesn't mean that arrays "take" those, but
    > only that such values get automatically converted to int before being
    > taken by the array for indexing.
    >
    > An example for something really "taking" byte-values:
    > foo(byte b) { ... }


    --
    Lew
     
    Lew, Aug 17, 2011
    #14
  15. On 17.08.2011 16:17, Lew wrote:
    > Andreas Leitgeb wrote:
    >> Arved Sandstrom<> wrote:
    >>> Lew wrote:
    >>>> JLS 10: [...] IOW, you never index arrays with a byte, char or
    >>>> short. [...]
    >>> I'm feeling slow this morning: how do we get problems with
    >>> byte->int, short->int, or char->int again?

    >
    > One gets problems with byte->int and short->int with array indexes
    > the way one gets into trouble with those widening conversions
    > generally. The usual suspect is the lack of unsigned versions, so
    > widening a (byte)0xA0, for example, would result in a negative
    > index.
    >
    > One gets into trouble generally in programming when one thinks one
    > thing is going on ("index takes a byte") whilst ignoring what's
    > really going on (there's a widening conversion involved). You might
    > get away with it most of the time, but occasionally such things trip
    > you up.


    Why had a nice issue recently which exactly fits this bill: after over
    two months of uninterrupted, completely error free production usage the
    application suddenly stopped working giving weird error messages (there
    was an issue with the error reporting as well, but let's ignore that for
    the moment). Turns out this was the setup:

    1. There was an AtomicInteger initialized at startup with 0 which for
    every request coming into that system was incremented in a thread safe
    manner (incrementAndGet()).

    2. The result was used to index into an array with the quite obvious
    "arr[n % arr.length]".

    3. (left as exercise for the reader)

    Anybody who now thinks all is fine should stop coding Java immediately
    and go reading the language spec.

    > Why think about it imprecisely? Tell us the advantage of that,
    > please.


    Some may reason: Someone else might have to pay for the laziness. But
    then again, the risk is it might come right back haunting the
    originator. Well, no risk, no fun. :)

    Cheers

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Aug 17, 2011
    #15
  16. KevinSimonson

    markspace Guest

    On 8/17/2011 10:02 AM, Robert Klemme wrote:

    > 1. There was an AtomicInteger initialized at startup with 0 which for
    > every request coming into that system was incremented in a thread safe
    > manner (incrementAndGet()).



    I'd be shocked if an int actually overflowed when counting requests like
    this, but that's all I can think of. 2^31 is such a huge number, I
    didn't think you could get there in practical cases.


    > 2. The result was used to index into an array with the quite obvious
    > "arr[n % arr.length]".
    >
    > 3. (left as exercise for the reader)



    Assuming that the AtomicInteger did overflow, then n % y produces
    negative numbers if n is negative, a clear AIOOB.

    Try : arr[ Math.abs( n ) % arr.length ];
     
    markspace, Aug 18, 2011
    #16
  17. markspace <-@> wrote:
    > On 8/17/2011 10:02 AM, Robert Klemme wrote:
    >> 1. There was an AtomicInteger initialized at startup with 0 which for
    >> every request coming into that system was incremented in a thread safe
    >> manner (incrementAndGet()).

    >
    > I'd be shocked if an int actually overflowed when counting requests like
    > this, but that's all I can think of. 2^31 is such a huge number, I
    > didn't think you could get there in practical cases.


    Depends of course on the average number of requests per second:
    at about 800, you'll get first overflow roughly within a month.

    >> 2. The result was used to index into an array with the quite obvious
    >> "arr[n % arr.length]".
    >> 3. (left as exercise for the reader)

    >
    > Assuming that the AtomicInteger did overflow, then n % y produces
    > negative numbers if n is negative, a clear AIOOB.
    > Try : arr[ Math.abs( n ) % arr.length ];


    What was Math.abs(-2147483648) again? ;-)

    Rather: arr[ (n%arr.length + arr.length) % arr.length ]
     
    Andreas Leitgeb, Aug 18, 2011
    #17
  18. KevinSimonson

    markspace Guest

    On 8/17/2011 4:48 PM, Andreas Leitgeb wrote:
    >
    > What was Math.abs(-2147483648) again? ;-)
    >
    > Rather: arr[ (n%arr.length + arr.length) % arr.length ]



    Ah yes, good point. I'll have to keep that in mind.
     
    markspace, Aug 18, 2011
    #18
  19. KevinSimonson

    Eric Sosman Guest

    On 8/17/2011 1:02 PM, Robert Klemme wrote:
    > On 17.08.2011 16:17, Lew wrote:
    >> Andreas Leitgeb wrote:
    >>> Arved Sandstrom<> wrote:
    >>>> Lew wrote:
    >>>>> JLS 10: [...] IOW, you never index arrays with a byte, char or
    >>>>> short. [...]
    >>>> I'm feeling slow this morning: how do we get problems with
    >>>> byte->int, short->int, or char->int again?

    >>
    >> One gets problems with byte->int and short->int with array indexes
    >> the way one gets into trouble with those widening conversions
    >> generally. The usual suspect is the lack of unsigned versions, so
    >> widening a (byte)0xA0, for example, would result in a negative
    >> index.
    >>
    >> One gets into trouble generally in programming when one thinks one
    >> thing is going on ("index takes a byte") whilst ignoring what's
    >> really going on (there's a widening conversion involved). You might
    >> get away with it most of the time, but occasionally such things trip
    >> you up.

    >
    > Why had a nice issue recently which exactly fits this bill: after over
    > two months of uninterrupted, completely error free production usage the
    > application suddenly stopped working giving weird error messages (there
    > was an issue with the error reporting as well, but let's ignore that for
    > the moment). Turns out this was the setup:
    >
    > 1. There was an AtomicInteger initialized at startup with 0 which for
    > every request coming into that system was incremented in a thread safe
    > manner (incrementAndGet()).
    >
    > 2. The result was used to index into an array with the quite obvious
    > "arr[n % arr.length]".
    >
    > 3. (left as exercise for the reader)
    >
    > Anybody who now thinks all is fine should stop coding Java immediately
    > and go reading the language spec.


    Yes, but what has this error to do with widening conversions,
    or conversions of any kind? It's GIGO, pure and simple.

    --
    Eric Sosman
    d
     
    Eric Sosman, Aug 18, 2011
    #19
  20. KevinSimonson

    Arne Vajhøj Guest

    On 8/16/2011 11:20 PM, markspace wrote:
    > On 8/16/2011 6:56 PM, Arne Vajhøj wrote:
    >> byte/short/int/long integer types

    >
    > OK, you mean for indexes?


    No, in general.

    Arne
     
    Arne Vajhøj, Aug 18, 2011
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rfractal30
    Replies:
    6
    Views:
    498
    rfractal30
    Feb 25, 2005
  2. David R. Throop
    Replies:
    0
    Views:
    433
    David R. Throop
    May 6, 2005
  3. Replies:
    8
    Views:
    462
    Fhulu Lidzhade
    Jan 23, 2006
  4. Kevin Neilson

    Assigning Values to Enumerated Types

    Kevin Neilson, May 7, 2008, in forum: VHDL
    Replies:
    9
    Views:
    611
    Kevin Neilson
    May 9, 2008
  5. Immortal Nephi
    Replies:
    4
    Views:
    420
    Öö Tiib
    Aug 24, 2010
Loading...

Share This Page