methods with "short"-typed arguments.

Discussion in 'Java' started by Andreas Leitgeb, Oct 7, 2008.

  1. Given a method:
    void foo (int x, short y) { ... }

    How would I call it with an immediate value for the second argument?

    foo ( 42, (short)43);

    Or did I miss some postfix-char for short literals (like "L" for long)?
    (according to http://mindprod.com/jgloss/jcheat.html there isn't one)

    Why is this cast necessary at all?
    Why doesn't the /$(%$&/ compiler notice, that 43 is just fine and
    provably without any loss of real information castable to a short?

    Instead it tells me:
    Test1.java:29: foo(int,short) in Test1 cannot be applied to (int,int)
    foo( someIntVar, 43 );


    PS: Yes, yes, changing foo to (int,int) would solve the problem, too,
    but that's a different story.

    PPS: don't take my swear-chars used with "compiler" too literally.
    Surely, the compiler is "/$(%$&/" only because some /$(%$&/ speci-
    fication demanded it to be so.
    Andreas Leitgeb, Oct 7, 2008
    #1
    1. Advertising

  2. Andreas Leitgeb

    Lew Guest

    On Oct 7, 10:33 am, bugbear <bugbear@trim_papermule.co.uk_trim> wrote:
    > Andreas Leitgeb wrote:
    > > Given a method:
    > >    void foo (int x, short y) { ... }

    >
    > > How would I call it with an immediate value for the second argument?

    >
    > >   foo ( 42, (short)43);

    >
    > > Or did I miss some postfix-char for short literals (like "L" for long)?
    > > (according tohttp://mindprod.com/jgloss/jcheat.htmlthere isn't one)

    >
    > I think you can "just do it"
    >
    > http://www.janeg.ca/scjp/lang/literals.html
    >
    >  >> If an int literal is assigned to a short or
    >  >> a byte and it's value is within legal
    >  >> range, the literal is assumed to be a short or a byte.
    >
    > I think parameter passing is same as assignment.


    It pays to check.

    <http://java.sun.com/docs/books/jls/third_edition/html/
    conversions.html#5.3>
    > Method invocation conversions specifically do not include the implicit narrowing
    > of integer constants which is part of assignment conversion.


    --
    Lew
    Lew, Oct 7, 2008
    #2
    1. Advertising

  3. Andreas Leitgeb

    Lew Guest

    Lew wrote:
    > <http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.3>


    Which entry, incidentally, includes an answer to the OP's question.

    --
    Lew
    Lew, Oct 7, 2008
    #3
  4. Lew <> wrote:
    > Lew wrote:
    >> <http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.3>

    > Which entry, incidentally, includes an answer to the OP's question.


    Indeed. The jls is the one to attribute the swear-chars to. (see
    original post of this thread)
    Andreas Leitgeb, Oct 7, 2008
    #4
  5. Andreas Leitgeb wrote:
    > Given a method:
    > void foo (int x, short y) { ... }
    >
    > How would I call it with an immediate value for the second argument?
    >
    > foo ( 42, (short)43);
    >
    > Why is this cast necessary at all?


    While you said you didn't want to be told based on the JLS, it is
    actually informative as to why it's done this way:

    «Method invocation conversions specifically do not include the implicit
    narrowing of integer constants which is part of assignment conversion.
    The designers of the Java programming language felt that including these
    implicit narrowing conversions would *add additional complexity* to the
    overloaded method matching resolution process.

    Thus, the example:

    class Test {
    static int m(byte a, int b) { return a+b; }
    static int m(short a, short b) { return a-b; }
    public static void main(String[] args) {
    System.out.println(m(12, 2));
    }
    }

    [ ... ] A language that included implicit narrowing of integer constants
    would *need additional rules to resolve cases* like this example.»

    (emphasis added, removed references and non-pertinent material)

    In short, it's an idea that seems easy to put into practice but quickly
    runs into pitfalls when you get to the corner cases that compilers have
    to warn about.

    To paraphrase what somebody once said about the design of CSS, designing
    a programming language specification requires you to specify what
    happens in the edgiest edge cases. You might not write code that has a
    method name overloaded to have every possible pair of primitive types,
    but the compiler still has to worry about that case.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Oct 7, 2008
    #5
  6. Joshua Cranmer <> wrote:
    > To paraphrase what somebody once said about the design of CSS, designing
    > a programming language specification requires you to specify what
    > happens in the edgiest edge cases. You might not write code that has a
    > method name overloaded to have every possible pair of primitive types,
    > but the compiler still has to worry about that case.
    >


    First of all, I thank for the reference to the original reasoning
    behind that behaviour.

    I'd find it ok for the compiler to be fussy in light of two
    or more overload-candidates, but less so in light of only
    one candidate.

    Also, I don't see the principial difference between widening
    a small integral primitive type (if taken as byte, and upcasted/
    widened to short or int as opportune) and up-casting in a class
    tree.

    It is no problem for the compiler to deal with
    ... methodA(Object o, Integer i) ...
    ... methodA(Number n1,Number n2) ...
    methodA ( new Integer(42), new Integer(43) );
    and correctly recognize this particular situation as ambiguous,
    but successfully call the remaining method, once I remove one of
    the candidates.

    If the compiler (in accordance with a virtual "corrected jls")
    treated byte-short-integer like Integer-Number-Object, with
    small numeric literal considered to be byte/short literals and
    implicitly "upcasted" to int as needed, and if it treated resulting
    possible ambiguities of called methods the same way as with Classes,
    then I'd be a lot more happy. (now isn't that a worthy goal?? :)

    I know it isn't so, but it would be just as reasonable, even less
    complex, and be just so much better :)
    Andreas Leitgeb, Oct 7, 2008
    #6
  7. Andreas Leitgeb

    Guest

    On Oct 7, 11:00 am, Lew <> wrote:
    > On Oct 7, 10:33 am, bugbear <bugbear@trim_papermule.co.uk_trim> wrote:
    >
    >
    >
    > > Andreas Leitgeb wrote:
    > > > Given a method:
    > > > void foo (int x, short y) { ... }

    >
    > > > How would I call it with an immediate value for the second argument?

    >
    > > > foo ( 42, (short)43);

    >
    > > > Or did I miss some postfix-char for short literals (like "L" for long)?
    > > > (according tohttp://mindprod.com/jgloss/jcheat.htmlthereisn't one)

    >
    > > I think you can "just do it"

    >
    > >http://www.janeg.ca/scjp/lang/literals.html

    >
    > > >> If an int literal is assigned to a short or
    > > >> a byte and it's value is within legal
    > > >> range, the literal is assumed to be a short or a byte.

    >
    > > I think parameter passing is same as assignment.

    >
    > It pays to check.
    >
    > <http://java.sun.com/docs/books/jls/third_edition/html/
    > conversions.html#5.3>
    >
    > > Method invocation conversions specifically do not include the implicit narrowing
    > > of integer constants which is part of assignment conversion.


    That all literals are of int type is a misfeature, IMO - the literal 1
    should be of type byte, which can be wideningly-converted to any of
    short, int, long, float, or double quite safely. Similarly, 128
    should be of type short, and 32768 of type int. This'd probably
    eliminate the need for an explicit 'L' qualifier: all literals greater
    than 2,147,483,647 or less than -2,147,483,648 would logically be of
    type 'long' without further effort.

    We'd still need F for floats, though.

    Alternately, the type suffixes for literals should be more thorough:
    suffixes for literals of all numeric primitive types, including char.
    The "implicit narrowing for assignment only" special case is confusing
    and unnecessary.

    -o
    , Oct 7, 2008
    #7
  8. <> wrote:
    > That all literals are of int type is a misfeature,

    numeric literals, of course. There are also String-literals, ...

    > IMO - the literal 1
    > should be of type byte, which can be wideningly-converted to any of
    > short, int, long, float, or double quite safely. Similarly, 128
    > should be of type short, and 32768 of type int. This'd probably
    > eliminate the need for an explicit 'L' qualifier:


    Mostly, but not entirely!
    1024 * 1024 * 1024 * 4 == 0
    1024 * 1024 * 1024 * 4L == 4294967296L
    Sometimes you need to specify a small literal as being
    of some wider type, to ensure the math is done the right
    way. That's ok.

    > all literals greater
    > than 2,147,483,647 or less than -2,147,483,648 would logically be of
    > type 'long' without further effort.
    > We'd still need F for floats, though.

    float and double are different beasts :)

    > Alternately, the type suffixes for literals should be more thorough:
    > suffixes for literals of all numeric primitive types, including char.


    At least better than the status quo.

    > The "implicit narrowing for assignment only" special case is confusing
    > and unnecessary.


    yep, 100% agree.
    Andreas Leitgeb, Oct 7, 2008
    #8
  9. Andreas Leitgeb

    Tom Anderson Guest

    On Tue, 7 Oct 2008, wrote:

    > On Oct 7, 11:00 am, Lew <> wrote:
    >> On Oct 7, 10:33 am, bugbear <bugbear@trim_papermule.co.uk_trim> wrote:
    >>
    >>> Andreas Leitgeb wrote:
    >>>> Given a method:
    >>>> void foo (int x, short y) { ... }
    >>>>
    >>>> How would I call it with an immediate value for the second argument?
    >>>>
    >>>> foo ( 42, (short)43);

    >
    > That all literals are of int type is a misfeature, IMO - the literal 1
    > should be of type byte, which can be wideningly-converted to any of
    > short, int, long, float, or double quite safely. Similarly, 128 should
    > be of type short, and 32768 of type int. This'd probably eliminate the
    > need for an explicit 'L' qualifier: all literals greater than
    > 2,147,483,647 or less than -2,147,483,648 would logically be of type
    > 'long' without further effort.


    Hmm. This doesn't feel like a good idea to me.

    > We'd still need F for floats, though.
    >
    > Alternately, the type suffixes for literals should be more thorough:
    > suffixes for literals of all numeric primitive types, including char.
    > The "implicit narrowing for assignment only" special case is confusing
    > and unnecessary.


    I like this suggestion best. As Tim Peters says, "explicit is better than
    implicit".

    tom

    --
    Wikipedia topics: lists of trains, Mortal Kombat characters, one-time
    villains from Mario games, road intersections, boring suburban schools,
    garage bands, cats, webcomics, Digimon, Bionicle characters, webforums,
    characters from English soap operas, and Mortal Kombat characters that
    don't exist -- Uncyclopedia
    Tom Anderson, Oct 7, 2008
    #9
  10. Tom Anderson wrote:
    > On Tue, 7 Oct 2008, wrote:

    ....
    >> We'd still need F for floats, though.
    >>
    >> Alternately, the type suffixes for literals should be more thorough:
    >> suffixes for literals of all numeric primitive types, including char.
    >> The "implicit narrowing for assignment only" special case is confusing
    >> and unnecessary.

    >
    > I like this suggestion best. As Tim Peters says, "explicit is better
    > than implicit".


    I don't see why, except for the long and float cases, suffixes are
    better than casts.

    A suffix is needed for long because the default integer type is
    narrower. A suffix is needed for float to avoid doing two rounding steps.

    Neither issue applies to (short)42.

    Patricia
    Patricia Shanahan, Oct 7, 2008
    #10
  11. Andreas Leitgeb

    Lew Guest

    Andreas Leitgeb wrote:
    > First of all, I thank for the reference to the original reasoning
    > behind that behaviour.


    The JLS is often, but not always, the place to find the reasoning for
    Java restrictions.

    > Also, I don't see the principial difference between widening
    > a small integral primitive type (if taken as byte, and upcasted/
    > widened to short or int as opportune) and up-casting in a class
    > tree.
    > ...
    > If the compiler (in accordance with a virtual "corrected jls")
    > treated  byte-short-integer  like  Integer-Number-Object, with
    > small numeric literal considered to be byte/short literals and
    > implicitly "upcasted" to int as needed, and if it treated resulting
    > possible ambiguities of called methods the same way as with Classes,
    > then I'd be a lot more happy.  (now  isn't that a worthy goal?? :)
    >
    > I know it isn't so, but it would be just as reasonable, even less
    > complex, and be just so much better :)


    JLS 5.3 indicates that implicit widening conversions are permitted in
    a method invocation.

    > Method invocation conversion is applied to each argument value in a method or constructor
    > invocation (§8.8.7.1, §15.9, §15.12): the type of the argument expression must be converted
    > to the type of the corresponding parameter. Method invocation contexts allow the use of one
    > of the following:
    > ...
    > * a widening primitive conversion


    Happy?

    --
    Lew
    Lew, Oct 7, 2008
    #11
  12. On Oct 7, 2:28 pm, Andreas Leitgeb <>
    wrote:
    > <> wrote:
    > > That all literals are of int type is a misfeature,

    >
    > numeric literals, of course.  There are also String-literals, ...
    >
    > > IMO - the literal 1
    > > should be of type byte, which can be wideningly-converted to any of
    > > short, int, long, float, or double quite safely.  Similarly, 128
    > > should be of type short, and 32768 of type int.  This'd probably
    > > eliminate the need for an explicit 'L' qualifier:

    >
    > Mostly, but not entirely!
    >    1024 * 1024 * 1024 * 4  == 0
    >    1024 * 1024 * 1024 * 4L  == 4294967296L
    > Sometimes you need to specify a small literal as being
    > of some wider type, to ensure the math is done the right
    > way.  That's ok.


    That's an ugly edge case, for sure. The approach a lot of languages
    have taken (going back at least to Lisp, and viable for imperative
    languages since at least Smalltalk) is that numbers are instances of
    an Integer or Number class, and operations return new instances; under
    the hood, small numbers are represented using hardware ints and large
    numbers using a bignum class, but all operations are in terms of
    Number, not of hardware-int-Number or bignum-Number.

    As far as I understand it, Java acquired primitives as a sop for
    people coming to the language from C++; since that's no longer a major
    concern, and since techniques for making object-like hardware ints
    fast are fairly well known, I don't see a lot of value in keeping
    primitives any more. Several newer JVM languages seem to agree; both
    Scala and Groovy use a number class for everything, even given the
    existing performance levels.

    -o
    Owen Jacobson, Oct 8, 2008
    #12
  13. On Oct 7, 3:55 pm, Patricia Shanahan <> wrote:
    > Tom Anderson wrote:
    > > On Tue, 7 Oct 2008, wrote:

    > ...
    > >> We'd still need F for floats, though.

    >
    > >> Alternately, the type suffixes for literals should be more thorough:
    > >> suffixes for literals of all numeric primitive types, including char.
    > >> The "implicit narrowing for assignment only" special case is confusing
    > >> and unnecessary.

    >
    > > I like this suggestion best. As Tim Peters says, "explicit is better
    > > than implicit".

    >
    > I don't see why, except for the long and float cases, suffixes are
    > better than casts.


    There's a psychological reason (cases where casts are necessary
    encourages people to use casts in other places) and a practical one (a
    suffix character is shorter and potentially clearer). I don't like
    suffixes at all; an ideal situation wouldn't require qualifying to the
    compiler that, for example, literal 400 is assignable to short -- it
    can work that out just fine for itself since all numeric types have
    well-defined ranges -- but the JLS forbids it from doing so.

    > A suffix is needed for long because the default integer type is
    > narrower. A suffix is needed for float to avoid doing two rounding steps.


    Floating-point initialization is a weird beast; the literal in the
    code actually identifies "the closest representable value in FP system
    X", where X is either float or double, and the density of possible
    values at any given point is different for both types. I'd prefer to
    eliminate the float type entirely (leaving 'double'; it might be worth
    renaming double) in some hypothetical version of Java, since it's
    rarely faster any more and always gives worse precision, but making
    the compiler aware of which type the literal 1.2 is being assigned to
    would be an acceptable solution, in line with making integer literals
    of the narrowest applicable type.
    Owen Jacobson, Oct 8, 2008
    #13
  14. On Oct 7, 4:48 pm, Lew <> wrote:

    > Andreas Leitgeb wrote:
    >
    > > If the compiler (in accordance with a virtual "corrected jls")
    > > treated  byte-short-integer  like  Integer-Number-Object, with
    > > small numeric literal considered to be byte/short literals and
    > > implicitly "upcasted" to int as needed, and if it treated resulting
    > > possible ambiguities of called methods the same way as with Classes,
    > > then I'd be a lot more happy.  (now  isn't that a worthy goal?? :)

    >
    > > I know it isn't so, but it would be just as reasonable, even less
    > > complex, and be just so much better :)

    >
    > JLS 5.3 indicates that implicit widening conversions are permitted in
    > a method invocation.


    I can think of no places where the JLS forbids an implicit widening
    conversion, come to think of it; if there are any, there probably
    shouldn't be.

    -o
    Owen Jacobson, Oct 8, 2008
    #14
  15. Andreas Leitgeb

    Arne Vajhøj Guest

    Owen Jacobson wrote:
    > That's an ugly edge case, for sure. The approach a lot of languages
    > have taken (going back at least to Lisp, and viable for imperative
    > languages since at least Smalltalk) is that numbers are instances of
    > an Integer or Number class, and operations return new instances; under
    > the hood, small numbers are represented using hardware ints and large
    > numbers using a bignum class, but all operations are in terms of
    > Number, not of hardware-int-Number or bignum-Number.
    >
    > As far as I understand it, Java acquired primitives as a sop for
    > people coming to the language from C++; since that's no longer a major
    > concern, and since techniques for making object-like hardware ints
    > fast are fairly well known, I don't see a lot of value in keeping
    > primitives any more. Several newer JVM languages seem to agree; both
    > Scala and Groovy use a number class for everything, even given the
    > existing performance levels.


    I find it likely that the next big language will have such
    a feature.

    Type precision could become a thing of the past like
    deallocation of memory.

    But today we have Java and I don't think it is possible
    to make this kind of changes without breaking existing
    code, so we have what we have in Java and will have it for
    the 1-3 decades that Java will last.

    Arne
    Arne Vajhøj, Oct 8, 2008
    #15
  16. Andreas Leitgeb

    Arne Vajhøj Guest

    wrote:
    > That all literals are of int type is a misfeature, IMO - the literal 1
    > should be of type byte, which can be wideningly-converted to any of
    > short, int, long, float, or double quite safely. Similarly, 128
    > should be of type short, and 32768 of type int. This'd probably
    > eliminate the need for an explicit 'L' qualifier: all literals greater
    > than 2,147,483,647 or less than -2,147,483,648 would logically be of
    > type 'long' without further effort.


    It is possible.

    But I really don't like the concept of the type depending
    on the value.

    Worst case would be a constant (static final) that is changed
    and then causes a call to use another method due to different
    overloaded arguments.

    > Alternately, the type suffixes for literals should be more thorough:
    > suffixes for literals of all numeric primitive types, including char.


    That on the other hand would be nice !

    Arne
    Arne Vajhøj, Oct 8, 2008
    #16
  17. Lew <> wrote:
    > JLS 5.3 indicates that implicit widening conversions are permitted in
    > a method invocation.
    >
    >> Method invocation conversion is applied to each argument value in a method or constructor
    >> invocation (§8.8.7.1, §15.9, §15.12): the type of the argument expression must be converted
    >> to the type of the corresponding parameter. Method invocation contexts allow the use of one
    >> of the following:
    >> ...
    >> * a widening primitive conversion

    >
    > Happy?


    Halfly. So the widening is already in place, so the only part yet
    missing is starting small numeric literals as the narrowest feasible
    primitive type, so that widening actually has a chance of occurring
    in more situations than just int->long.
    As an extra bonus, no special rules for assignment would then be
    necessary anymore.

    Then me happy.
    Andreas Leitgeb, Oct 8, 2008
    #17
  18. Arne Vajhøj <> wrote:
    > Worst case would be a constant (static final) that is changed
    > and then causes a call to use another method due to different
    > overloaded arguments.


    probably a bad example, because if you stored a literal in a
    static final then it does have some very explicit type.
    static final short ANSWER = 42;

    while 42 should be treated as a byte, ANSWER is definitely
    a short, despite it's value being inlined by the compiler.

    If I had static final byte FOO = 1; I could use FOO for
    calling a method taking a byte or a short even now.

    If we're leaving static finals aside now, and use literals, then
    it would be possible, that where previously the "int"-variant of
    a method was called, that then a "byte"-variant could be called,
    or in some multi-arguments cases the compiler could then error out
    complaining about ambiguity, as it already does in some class-
    hierarchy-related situations.

    Having explicit byte- and short- literal postfixes would indeed
    prevent a change in behaviour of old code. I think I start to like
    that idea, as it's the least even possibly painful thing.

    PS: to be honest, a postfix for byte/short literals would be mostly
    syntactic sugar for the cast. I think it's good sugar, others may
    disagree.
    Andreas Leitgeb, Oct 8, 2008
    #18
  19. Lew <> wrote:
    > You're not supposed to put magic numbers in code anyway. Declare static final
    > variables to hold your constants, then you get the rest of your wish.


    Not all numbers are magic ;-)

    > static final byte MAGIC_NUMBER = 23;
    > invoke( MAGIC_NUMBER );


    Good(tm) idea: I create Literals.java with roughly these contents:
    class Literals {
    public static final byte bm128=-128,bm127=-127,...,bm1=-1,
    b0=0,b1=1,b2=2,...,b127=127;
    public static final short sm32768=-32768,...,sm129=-129,...,sm1=-1,
    s0=0,s1=1,...,s128=128,...,s32767=32767;
    }
    (probably I'm gonna need to split it into two
    classes, one for >=0 and one for <0 "literals"
    to avoid exceeding max# of fields per class)

    Then use:
    static import path.to.Literals.*;
    ... foo(s4200, bm42); // foo(short,byte)

    and finally end up with a case-sensitive "prefix" instead of a
    case-insensitive postfix notation.

    PS: yeuch, but it would work.
    Andreas Leitgeb, Oct 8, 2008
    #19
  20. Andreas Leitgeb

    Lew Guest

    Andreas Leitgeb wrote:
    > Good(tm) idea: I create Literals.java  with roughly these contents:
    >   class Literals {
    >     public static final byte bm128=-128,bm127=-127,...,bm1=-1,
    >                              b0=0,b1=1,b2=2,...,b127=127;
    >     public static final short sm32768=-32768,...,sm129=-129,...,sm1=-1,
    >                              s0=0,s1=1,....,s128=128,...,s32767=32767;


    Seriously? You explicitly list 65,536 literal short values? You've
    actually done this?

    >   }
    > (probably I'm gonna need to split it into two
    > classes, one for >=0 and one for <0 "literals"
    > to avoid exceeding max# of fields per class)


    I am just shaking my head in incredulity.

    > Then use:
    >   static import path.to.Literals.*;
    >   ...  foo(s4200, bm42);   // foo(short,byte)
    >
    > and finally end up with a case-sensitive "prefix" instead of a
    > case-insensitive postfix notation.


    Here's a case-sensitive prefix that puts less strain on the constant
    pool and the number of allowable fields per class. Let's say you have
    a method that takes a 'short' argument:

    public void foo( short val );

    The case-sensitive prefix would look like this:

    holder.foo( (short) 8191 );

    --
    Lew
    Lew, Oct 8, 2008
    #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. Ersin Gençtürk
    Replies:
    1
    Views:
    3,460
    Ersin Gençtürk
    Oct 6, 2004
  2. David Geering

    longs, long longs, short short long ints . . . huh?!

    David Geering, Jan 8, 2007, in forum: C Programming
    Replies:
    15
    Views:
    544
    Keith Thompson
    Jan 11, 2007
  3. Replies:
    4
    Views:
    798
    Kaz Kylheku
    Oct 17, 2006
  4. Ioannis Vranos

    unsigned short, short literals

    Ioannis Vranos, Mar 4, 2008, in forum: C Programming
    Replies:
    5
    Views:
    657
    Eric Sosman
    Mar 5, 2008
  5. Yingjie Lan
    Replies:
    4
    Views:
    284
    John Nagle
    Jan 29, 2010
Loading...

Share This Page