7.0 wishlist?

Discussion in 'Java' started by Harold Yarmouth, Oct 29, 2008.

  1. There's probably plenty of these floating around already, but here's
    bits of mine:

    * Sort-of structural typing. Any object can be used where an interface
    type is expected if it has the right set of method signatures, whether
    or not it "implements" the interface using that keyword. (It still must
    to inherit constants defined in the interface, and methodless interfaces
    would not get this behavior else everything becomes, among other things,
    serializable!)

    * Allow extending final classes, subject to the constraint that new
    instance fields cannot be defined and none of the final class's methods
    can be overriden regardless of whether the method is explicitly "final".
    Essentially allows wrapping final classes.

    * Add an unsigned byte type.

    * Add some way to specify that something should never be null. Perhaps a
    ! or a * before or after the variable name or type name.

    * Allow omitting the names of unused parameters. Common cases would include:
    public void ActionPerformed (ActionEvent) {
    foo.setVisible(false);
    bar.purge();
    }

    catch (IOException) {
    return false;
    }

    * Constructor type inference. Also allow an alternate constructor
    syntax that doesn't repeat the class name, say using * in its place.
    So we can avoid some cases of repeating type names, assign
    Map<K, V> myMap = new HashMap(), and perhaps also do e.g.
    ConcreteType x = new(argument) where ConcreteType has a suitable
    public one-argument constructor.

    * Disallow public constructors on abstract classes. They are not
    callable by any more code than a protected constructor anyway.

    * When a type has a one-argument plus() method, + can be used when the
    left hand operand is of that type and the right hand operand is of an
    argument type for which the former has a one-argument plus() method.
    This + binds with the usual precedence for binary + and x + y is
    simply an alternate way of saying x.plus(y). Similarly .times and
    some others. <= and >= and < and > use compareTo. === and !== get
    added and use .equals, and bind with the same precedence as == and !=.
    x + y * z is converted by the compiler to the same bytecodes as
    x.plus(y.times(z)) and x * y + z to x.times(y).plus(z). += and the
    like combine assignment with addition. ++ does .plus(1) and --
    .plus(-1). Unary - does .negated() and x - y is x.plus(y.negated()).
    For consistency's sake a .plus method is added to String that returns
    a concatenation. None of the +=, *= etc. change objects, only
    reassigning references; String s; ... s += t is legal and reassigns
    the reference s to a new string object. Compiler remains free to
    optimize string accumulations to use StringBuilder under the hood,
    and programmer remains encouraged to use it explicitly at least in
    loops. StringBuilder also gets a .plus method. Both of these take
    Object and use its toString if necessary.
    In short, a hygienic form of operator overloading.

    * Clean up ImageIO and JAI. A lot of the code in these throws various
    RuntimeExceptions in response to seeing something it doesn't like in
    file or network data. Really, only checked exceptions (and mainly
    IOException) should be thrown in response to seeing something you
    don't like in externally-obtained data.

    * Inverse to the above, get rid of some awkward checked exceptions or
    make them RuntimeExceptions. Culprits include NoSuchAlgorithmException
    (usually, the algorithm name is hard-coded and so this exception
    signals a bug close to where it is thrown, rather than an erroneous
    or unexpected condition the program is expected to cope with in
    production) and most others where the usual handling by the coder is
    to let the exception kill the thread, catch it and throw new
    RuntimeException() or Error(), or catch it and do nothing.

    * Dead code in a method should be a warning, not an error.

    * Hiding a local variable with a nested-scope local variable should be a
    warning, not an error.

    * Provide a better way to deal with OutOfMemoryError or low memory in
    general, as well as a JVM mode in which a program can use as much
    memory as it needs, but the VM will also not greedily take everything
    the OS will give it. In this, it may maintain a "load factor" similar
    to a HashMap for the entire heap, trying to keep it near 75% full, and
    a JVM option to tweak this may exist. Higher gives poorer GC
    performance but leaves more RAM for the OS; lower gives better GC
    performance but uses more memory; no value throws OOME unless the OS
    won't give the Java process memory it needs.
    Add System.addLowMemoryListener() or similarly. Listeners are notified
    if free memory dips below some threshold, running on a temporary
    worker thread and perhaps doing things like flush caches.

    * Provide a nicer way to deal with resource release. Possibly have a
    Releasable interface added, which specifies a dispose() method and
    which would be applied to many objects like streams and JFrames
    that already have such a method or a similar method. Methods that
    get a non-Swing-container Releasable and don't either return it or
    use try...finally to dispose it generate a warning. A do() method
    in the same interface takes a Runnable and calls the runnable
    then disposes the releasable.

    * Especially given the above: a shortcut for new Runnable() { public
    void run () { ... }}. Let a brace block appearing where an expression
    is expected be equivalent to the above, with the contents of the
    brace block in place of the ellipsis (...). Then you can do e.g.
    SwingUtilities.invokeLater({foo.setVisible(true);});
    Also allow this short form to throw checked exceptions, which it
    will be assumed the calling code might throw. (So
    SwingUtilities.invokeLater({myOutputStream.write("foo");});
    would be treated by the compiler as able to throw IOException,
    though in fact it would arise in another thread entirely; on
    the other hand, using Runnables as custom control blocks like
    the Releasable.do() suggested above would result in the
    exception being thrown out of do() and into the code that
    physically contains the block. Most invocations of runnables
    into separate threads are not with ones that throw unhandled checked
    exceptions anyway.

    * Allow array literals in expressions other than assignment RHS.
    Why the devil is foo(1, "string literal", 3) allowed but
    foo(1, {array, literal}, 3) is not, even when foo's second
    parameter type is Object?
    (The above two can be disambiguated: array literals and statement
    blocks are syntactically distinguishable, and array literals will
    generally be used where the parameter type is an array type or
    Object and runnable literals where the parameter type is Runnable.)

    * Have array constructors added to the collection classes:
    (with the above as well)
    new HashSet({2, 3, 5, 7, 11, 13});
    new ArrayList({"foo", "bar", "baz", "quux"});
    new HashMap({{"key1", "value1"}, {"key2", "value2"}});

    * Add java.lang.Pair<K, V>. Make some existing classes Pair
    implementations, e.g. Dimension extends Pair<Integer, Integer>,
    possibly also Rectangle extends Pair<Dimension, Dimension>,
    Map.Entry<K,V> extends Pair<K,V>, etc.
    Two-element array literals allowed where Pair is expected and
    produce Pair literals.

    * [int x]; defines a final box containing an int, an instance of a
    Box<T> with T == Integer, which has methods T get() and void set(T).
    One can then do e.g.
    [JFrame foo = new JFrame()];
    ...
    SwingUtilities.invokeLater({foo.get().setVisible(true);});
    given the above runnable-literal suggestion.
    Add a : operator that expands to ".get()." and we have:
    SwingUtilities.invokeLater({foo:setVisible(true);});
    Almost a closure, there!
    The : operator also lets us use WeakReference and the like
    more nicely, if we add another touch to handle the case of null.
    ref:doSomething()?System.out.println("something was null!");, say.

    * In many more cases it might be useful to have a shortcut to
    if (x == null) value = this else value = that
    so how about more generally allowing x.foo?ifNull -- the ? clause
    is executed whenever x is null and the method call when it's not.
    Or just allow x?expression1:expression2 for non-Booleans testing
    for null.

    * Another source of boilerplate code is:
    Type t;
    try {
    t = someExpressionThatMayThrow();
    } catch (FooException e) {
    ...
    return/continue/break/throw foo/whatever
    }
    t.doSomething();

    where you don't want to doSomething() if the exception got raised,
    doSomething() itself may raise the same exception but it shouldn't be
    caught in the same catch, or similarly.
    Let an alternate form be:
    try {
    Type t = someExpressionThatMayThrow();
    } continue {
    t.doSomething();
    } catch (FooException e) {
    ...
    }
    which is not shorter, but doesn't break up t's declaration and
    assignment. This, among other things, lets t be final, and also
    lets the catch fall through without "t may not be assigned!". In
    some cases it may save lots of boilerplate code:
    Type t = null;
    try {
    t = someExpressionThatMayThrow();
    } catch (FooException e) {
    fooNotifier.logError(e.getMessage());
    failed = true;
    }
    if (t != null) {
    t.doSomething();
    }
    Yuck! This occurs a lot in I/O code though, usually with Type
    actually InputStream or one of its close relatives. Often we
    want to handle failure to open the stream specially versus
    a failure once we already have the stream open, though both
    throw IOException. Sometimes, for instance, we want to flag
    an error in some way if the open fails, but let the IOException
    bubble up to the caller if the subsequent I/O fails, as the
    latter is "more exceptional" than the former.
    The key to the above is to have t remain in scope in the
    "continue" block.
    (Other ugliness this might relieve includes some cases of nested try
    blocks.)

    * Full closures. Let anonymous inner classes access nonfinal local
    variables of the enclosing scope, by having the compiler put all
    such variables used by such inner classes transparently into an
    Object[] array rather than directly on the stack, or something of
    the sort. (The syntax of using them wouldn't change; only how they
    got stored, so they had mutable references on the heap, and thus also
    the bytecode generated where they were accessed. The compiler would
    also not need to generate type checks when dereferencing this array,
    as there'd be no way of getting at it directly in user code.)
    Furthermore, let {code} used as an expression rather than a statement
    stand for new Object() { public Type1 run(Type2 arg1, Type3 arg2...)
    { code }}. Add "it implements the interface if it is method-compatible
    with it" from high up on this list and this gets you Runnable literals
    in the void return, no arguments case. Types inferred by what the
    expression's type needs to be to fit -- there would need to be a new
    type in the system for type-tuples, which would also be useful for
    reifying generics and where the <void> tuple represents Runnable,
    <void, int> an interface specifying void run (int x), and so on.
    Lastly, closures could use "return return x" to throw a
    ClosureNonLocalReturnException wrapping an x, and passing a closure
    to a method would implicitly wrap the method call in try { ... }
    catch (ClosureNonLocalReturnException e) { return e.getWrapped(); }
    -- implementing non-local returns. (If the closure "escaped" its
    context and then non-local returned, it would manifest in a
    RuntimeException: the uncaught ClosureNonLocalReturnException.
    The JIT compiler could optimize the generation of nonlocal returns
    that proved to be always implicitly caught by eliding generation of
    their stack traces. (In practise, each nonlocal return would have
    to throw a new anonymous subclass of that exception -- each time
    a method was invoked that contained such closures it would cause
    the generation of a new anonymous subclass and that class would
    be caught by the implicit catch blocks in that invocation of that
    method. This would be the conceptual behavior, anyway. In actuality
    the generated bytecodes would probably look like those from an
    explicit throw of an exception that takes a wrapped value and
    an id integer, plus those from an explicit catch clause resembling
    if (e.getID() != id) throw e; return e.getWrapped();
    The method bytecode would also need to generate this id, and a new
    one each call; System.nanoTime() might work on present processors.
    An efficient atomic integer incrementor might be needed ultimately,
    or an efficient implementation of ThreadLocal, with a bipartite ID
    of the thread's identityHashCode and a thread-local incrementing ID.

    * Object.identityHashCode().

    * Equalizer to go with Comparator, provides equals and hashCode by
    proxy, can be used with HashSet and HashMap to provide substitute
    key equality and hash functions the way Comparator can provide a
    substitute compareTo for TreeSet and TreeMap.

    * WeakValueHashMap, LinkedWeakHashMap, and LinkedWeakValueHashMap.
    These would all be useful implementing caches where you want the
    mapping to go away if the value is no longer in use, but calls
    for the value to return the pre-existing object if one existed.
    WeakValueHashMap already sort-of exists in one under-the-hood bit
    of non-user-reusable Java: the implementation of string interning,
    starting whenever they finally got it to GC unused interned strings.
    Trying to implement one yourself is a bear, because there's no way
    to automatically do something when a reference dies.

    * ReferenceQueue.addListener(Reference r) to let you automatically do
    something when a reference is enqueued. Or provide a protected method
    in Reference that is called when the reference is cleared or is
    about to be cleared, so you can e.g. subclass WeakReference, override
    this method, and do something specific (such as remove a mapping
    from a map).
    Closest you can currently get is to use a WeakHashMap of the
    same object to
    new Object() { protected void finalize() { do.whatever(); }}
    and pray.

    * Allow subclassing an enum with the subclasses able to REMOVE (not
    add!) values. An enum that can be any of X, Y, or Z is a subtype,
    rather than a supertype, of one that can be any of X, Y, Z, A, or B
    because it is substitutable for the latter but not vice-versa; the
    actual created classes would be Super with subclasses Sub, Super.A,
    Super.B, Super.X, Super.Y, and Super.Z and subclasses of Sub Sub.X,
    Sub.Y, and Sub.Z, with some change to the underlying code to not treat
    Sub itself as an enum value for Super and to treat Sub.X, Sub.Y, and
    Sub.Z as convertible to their Super counterparts. The former change is
    easy: ignore non-leaf subclasses. The latter is also easy, so long as
    enum subclasses can't add methods, fields, or similarly.
    Might as well also allow creating supertypes, an enum with additional
    values that is assignable FROM the original enum but not TO it.
    These might be best implemented not as true under-the-hood subclasses
    at all, but as parallel types with implicit conversions among them.
     
    Harold Yarmouth, Oct 29, 2008
    #1
    1. Advertising

  2. Harold Yarmouth wrote:
    > There's probably plenty of these floating around already, but here's
    > bits of mine:
    >
    > * Sort-of structural typing. Any object can be used where an interface
    > type is expected if it has the right set of method signatures, whether
    > or not it "implements" the interface using that keyword. (It still must
    > to inherit constants defined in the interface, and methodless interfaces
    > would not get this behavior else everything becomes, among other things,
    > serializable!)


    I smell a lot of unexpected bugs coming from this. Note that if you
    already have the right method signatures, you could just take the
    interface onto the implements list.

    > * Allow extending final classes, subject to the constraint that new
    > instance fields cannot be defined and none of the final class's methods
    > can be overriden regardless of whether the method is explicitly "final".
    > Essentially allows wrapping final classes.


    No, essentially makes final classes worthless.

    > * Add some way to specify that something should never be null. Perhaps a
    > ! or a * before or after the variable name or type name.


    How about adding a @NotNull annotation and then running your own static
    checker?

    > * When a type has a one-argument plus() method, + can be used when the
    > left hand operand is of that type and the right hand operand is of an
    > argument type for which the former has a one-argument plus() method.


    [ ... ]

    A poor way of doing operator overloading. There are better proposals out
    there.

    > some others. <= and >= and < and > use compareTo. === and !== get
    > added and use .equals, and bind with the same precedence as == and !=.


    Except many other languages use == as equivalent to the equals method
    and === as equivalent to Java. Also note that you'll fall down with
    nulls here.

    > * Provide a better way to deal with OutOfMemoryError or low memory in
    > general, as well as a JVM mode in which a program can use as much
    > memory as it needs, but the VM will also not greedily take everything
    > the OS will give it.


    Judicious use of WeakReference and SoftReference helps, and there are
    also suitable APIs in java.lang.management that already provide much of
    this functinoality.

    > * Especially given the above: a shortcut for new Runnable() { public
    > void run () { ... }}.


    [ ... ]

    I take it you haven't heard of closures.

    > * Allow array literals in expressions other than assignment RHS.
    > Why the devil is foo(1, "string literal", 3) allowed but
    > foo(1, {array, literal}, 3) is not, even when foo's second
    > parameter type is Object?


    new Object[] {array, literal} ?

    > * Have array constructors added to the collection classes:
    > (with the above as well)
    > new HashSet({2, 3, 5, 7, 11, 13});
    > new ArrayList({"foo", "bar", "baz", "quux"});
    > new HashMap({{"key1", "value1"}, {"key2", "value2"}});


    new HashSet(Arrays.asList(2, 3, 5, 7, 11, 13));

    So much cleaner IMO.

    There's also this for the last one:
    new HashMap() {{
    this.put("key1", "value1");
    this.put("key2", "value2");
    }};

    > * In many more cases it might be useful to have a shortcut to
    > if (x == null) value = this else value = that
    > so how about more generally allowing x.foo?ifNull -- the ? clause
    > is executed whenever x is null and the method call when it's not.
    > Or just allow x?expression1:expression2 for non-Booleans testing
    > for null.


    x == null ? expr1 : expr2 is not at all verbose and much easier to
    distinguish on scanning.

    > * Full closures.


    Someone beat you to this.

    > * Allow subclassing an enum with the subclasses able to REMOVE (not
    > add!) values.


    Very ugly.

    Most of your features have little chance of being added since some are
    doable in existing syntax anyways, and many of them would require making
    deep changes for what I see as little value.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
     
    Joshua Cranmer, Oct 29, 2008
    #2
    1. Advertising

  3. Harold Yarmouth

    Mark Space Guest

    Harold Yarmouth wrote:
    > There's probably plenty of these floating around already, but here's


    <http://tech.puredanger.com/2008/08/02/java7-prediction-update/>


    > * Sort-of structural typing. Any object can be used where an interface
    > type is expected if it has the right set of method signatures, whether
    > or not it "implements" the interface using that keyword. (It still must


    Interesting but not my cuppa. Break down and just type "implements" on
    your class please.

    > * Allow extending final classes, subject to the constraint that new
    > instance fields cannot be defined and none of the final class's methods


    Feels yicky. Consider composition instead of inheritance.


    > * Add an unsigned byte type.


    Probably too late for this, but sure it would have been handy.

    >
    > * Add some way to specify that something should never be null. Perhaps a
    > ! or a * before or after the variable name or type name.


    Does this require a runtime check on each assignment? Could be a lot of
    overhead...

    > * Allow omitting the names of unused parameters. Common cases would
    > include:


    I agree with Joshua, typo-city.

    > * Constructor type inference. Also allow an alternate constructor


    Generic methods can do this now. I think it might be handy for Sun to
    provide some generic methods to initialize the classes you mention.
    Rolling your own for your own classes isn't hard.

    > * Disallow public constructors on abstract classes. They are not
    > callable by any more code than a protected constructor anyway.


    super();?

    >
    > * When a type has a one-argument plus() method, + can be used when the
    > left hand operand is of that type and the right hand operand is of an


    OK with me but apparently this ran into technical troubles. Too
    complicated for now.

    >
    > * Clean up ImageIO and JAI. A lot of the code in these throws various
    > RuntimeExceptions in response to seeing something it doesn't like in


    At least they shouldn't be throwing unsubclassed RuntimeException. Are
    they?


    > * Inverse to the above, get rid of some awkward checked exceptions or
    > make them RuntimeExceptions. Culprits include NoSuchAlgorithmException


    Probably also a good idea.

    > * Dead code in a method should be a warning, not an error.


    Sure, makes debugging hard. Or at least allow a switch to make it a
    warning during development.

    A good IDE will comeent out dead code in a hurry though...

    > * Hiding a local variable with a nested-scope local variable should be a
    > warning, not an error.


    Dunno about this, just pick a different variable name.

    > * Provide a better way to deal with OutOfMemoryError or low memory in


    Hmm, I haven't looked at any existing frameworks for using
    SoftReferences, but I'd head over to Apache.org and take a look.
    Personally I think the garbage collector is probably about as
    complicated at Sun can handle at this time.

    > the OS will give it. In this, it may maintain a "load factor" similar
    > to a HashMap for the entire heap, trying to keep it near 75% full, and


    It's been discussed here, at least. I don't know how hard this would
    be, but I'm in favor of it, Sun willing. The incremental garbage
    collector gets pretty close to this, imo. It slowly prunes out un-used
    objects as the program runs, thereby keeping actual memory footprint to
    a minimum. Used objects can't be pruned by anyone, of course.

    > * Provide a nicer way to deal with resource release. Possibly have a
    > Releasable interface added, which specifies a dispose() method and


    I think they already have as nice a method as they can. Use finalize()
    if you must. Personally I set all my windows to "DISPOSE_ON_CLOSE" so
    they just to it for me.


    > * Especially given the above: a shortcut for new Runnable() { public
    > void run () { ... }}. Let a brace block appearing where an expression


    Well... closures may be on their way. Let's hold out for the correct
    solution.

    > * Allow array literals in expressions other than assignment RHS.


    Java arrays need a type, I think, which isn't aways inferable from the
    context. Not sure how well this would work in practice.

    > * Have array constructors added to the collection classes:
    > new HashMap({{"key1", "value1"}, {"key2", "value2"}});


    This would be handy, but what type are those arrays?

    > * Add java.lang.Pair<K, V>. Make some existing classes Pair


    This is so easy to roll your own, I'm sure that's why no one has done it
    for you.

    > implementations, e.g. Dimension extends Pair<Integer, Integer>,


    I think if Sun started messing with these, they'd go the other way.
    Dimension is slow. Use the individual X and Y methods instead.

    > * [int x]; defines a final box containing an int, an instance of a


    > SwingUtilities.invokeLater({foo:setVisible(true);});


    Or you could substitute a "." for the ":" and save yourself a lot of
    useless code. :rollseyes:

    > * In many more cases it might be useful to have a shortcut to
    > if (x == null) value = this else value = that


    I'm with Joshua, the ternary operator is fine.

    > * Another source of boilerplate code is:


    > Let an alternate form be:
    > try {
    > Type t = someExpressionThatMayThrow();
    > } continue {
    > t.doSomething();
    > } catch (FooException e) {
    > ...


    No opinion. I've written your "yuck" code myself. It's really not that
    common though, usually just doing file IO, which can be encapsulated
    pretty well.

    >
    > * Full closures. Let anonymous inner classes access nonfinal local


    JSR is done, I think. I'm not really fond of more anonymous classes
    though, I wish something more efficient could be used.


    > * Object.identityHashCode().


    An un-overridable hashcode? I guess, though I wonder if all platforms
    can always provide an "identity" for each object. What happens when an
    object gets shipped across a network several times? Will it loose it's
    identity?


    > * Equalizer to go with Comparator, provides equals and hashCode by


    A lot of libraries need to change to use this. Sure, if someone is
    willing to do the work.

    > * WeakValueHashMap, LinkedWeakHashMap, and LinkedWeakValueHashMap.
    > These would all be useful implementing caches where you want the


    I think the Apache folks may have a framework or three. Didn't actually
    check though...

    > * ReferenceQueue.addListener(Reference r) to let you automatically do


    No opinion.

    > * Allow subclassing an enum with the subclasses able to REMOVE (not


    Probably going to break a lot of stuff and make enums a lot less
    efficient. Please roll your own removable enum.
     
    Mark Space, Oct 29, 2008
    #3
  4. Harold Yarmouth <> wrote:
    > * Sort-of structural typing. Any object can be used where an interface
    > type is expected if it has the right set of method signatures,


    There isn't any real distinction between marker interfaces
    like Cloneable and "normal" interfaces. As long as
    obj instanceof SomeEmptyInterface is not made trivially true
    (which of course it shouldn't be under any circumstances)
    it's also not possible to make obj instanceof FooInterface
    appear to be true, just based on existence of some methods.

    And any other type of compatibility inconsistent with the
    instanceof-operator is right out of question, anyway.

    I don't think this fits into Java.

    > * Allow extending final classes, subject to the constraint that new
    > instance fields cannot be defined and none of the final class's methods
    > can be overriden regardless of whether the method is explicitly "final".
    > Essentially allows wrapping final classes.


    Yes, yes, yes! Not sure, if you got that idea yourself, or
    from reading <>.
    (in case google distorts it: "slrngfmc50.4jb.avl" is the part
    before the "at")
    As I brought it, it would subsume the functionality
    of proposed typedefs plus add some more useful usecases.

    > * Add an unsigned byte type.

    adding unsigned primitive types of all sizes generally would be
    cool, but then Java should also spend some extra effort on sane
    semantics:
    e.g. any negative value would have to be trivially smaller
    than any unsigned value, and an unsigned value beyond the
    range of the other signed value would have to be trivially
    always larger. That is grossly unlike C's behaviour for
    operators with mixed-signedness operands. And that isn't
    yet all to it (what sign would be the result of mixed-
    signedness addition?)
    Complicated as that would become, I doubt it has any chance
    of getting into 7.0. I fear the problem about signed byte
    is too fubar'ed to be repaired anytime soon.

    > * Add some way to specify that something should never be null. Perhaps a
    > ! or a * before or after the variable name or type name.


    Sounds cool, principially, but I don't like to add a "line noise
    character" for that feature, but rather some keyword.
    It wouldn't be possible to create arrays of non-null types,
    unless there'd also be syntax to pre-initialize the elements.

    > * Allow omitting the names of unused parameters. Common cases would include:
    > public void ActionPerformed (ActionEvent) {

    Really little gain, given that most of the times one really should
    do something with the value (especially in catch-blocks), and in
    other cases, the name of some parameter gives a hint as to what
    is expected there, (and may be used as such by overrides).
    Also, for unused method-arguments, the name is usually referred to
    by the javadocs. You do javadoc your methods, don't you?

    > * Constructor type inference. Also allow an alternate constructor
    > syntax that doesn't repeat the class name, say using * in its place.

    May be useful in a few special cases, but sends a wrong message in
    most other cases:

    One shouldn't really use HashMap<...> typed variables in one's
    code, but rather Map<...> typed ones for more flexibility lateron
    (just assign a TreeMap instance to the Map variable instead of a
    HashMap and don't bother with having to change all the variable's
    types.)

    The proposal would encourage use of:
    HashMap<...> hashMap = new *(...);
    which would be a bad thing.

    (This argument doesn't apply against typdef'ing HashMap to MyTypeMap,
    since the alias could still be quite easily changed at one place, if
    so needed.)

    > * Disallow public constructors on abstract classes. They are not
    > callable by any more code than a protected constructor anyway.

    Indeed, for abstract classes' constructors: public is equivalent to
    protected. So public could be mapped to protected for those. I see
    no gain from that mapping, and even much less gain from demanding
    programmers to change "public" to "protected". Since they are in
    that case equivalent, it means it doesn't really narrow accessibility.
    (which otherwise is a generally good thing to do, of course)

    > * When a type has a one-argument plus() method, + can be used ...

    operator overloading through special method names and signatures.
    Quite a controversial topic.

    > * Clean up ImageIO and JAI. [w.r.t exceptions]
    > * Inverse to the above, get rid of some awkward checked exceptions [...]

    No opinion on those

    > * Dead code in a method should be a warning, not an error.

    agree! It came up already a couple of times in this group.

    > * Hiding a local variable with a nested-scope local variable should be a
    > warning, not an error.

    also agree, but without extra exclamation mark :)

    > * Provide a better way to deal with OutOfMemoryError or low memory in
    > general, as well as a JVM mode in which a program can use as much
    > memory as it needs, but the VM will also not greedily take everything
    > the OS will give it.

    long overdue... (i.e.: agree! )

    > no value throws OOME unless the OS won't give the Java process memory
    > it needs.


    It is still good to *be able to* limit a process' memory footprint.
    It just shouldn't be limited by default and then also too low (as it is now)
    I guess, you meant it that way, too.

    > Add System.addLowMemoryListener() or similarly. Listeners are notified
    > if free memory dips below some threshold, running on a temporary
    > worker thread and perhaps doing things like flush caches.

    That's the wrong approach. Rather let the application use
    SoftReferences:
    <http://java.sun.com/javase/6/docs/api/java/lang/ref/SoftReference.html>

    > * Provide a nicer way to deal with resource release.

    Hmm, beats me.
    I think that this lack of hookability into the GC's actual
    results is mostly by design. I do not entirely understand
    that design, either. I looked at the implementation of
    WeakHashMap, and while it gets the list of Objects on request
    (which is done in size(), isEmpty(), and a couple of other
    accessor methods), but there indeed is no way to be notified
    instantly upon GC (whenever that runs).
    I can only guess, that they don't want the little kids to drop
    cookie-crumbs *instantly* after having hoovered the room :)

    > * Especially given the above: a shortcut for new Runnable() { public
    > void run () { ... }}. Let a brace block appearing where an expression
    > is expected be equivalent to the above, with the contents of the
    > brace block in place of the ellipsis (...). Then you can do e.g.
    > SwingUtilities.invokeLater({foo.setVisible(true);});


    That appears to touch the "closures" topic, even though it's
    just suggested as syntactic sugar for certain anonymous classes.

    > Also allow this short form to throw checked exceptions, which it
    > will be assumed the calling code might throw. (So
    > SwingUtilities.invokeLater({myOutputStream.write("foo");});
    > would be treated by the compiler as able to throw IOException,
    > though in fact it would arise in another thread entirely;


    There is no sense for "SwingUtilities.invokeLater" to declare to throw
    any checked exceptions. Unlike C's "fork", the SwingUtilities.invokeLater
    doesn't "return twice": all the created threads don't know nuts about
    SwingUtilities.invokeLater. They just exist, and run run() as their
    toplevel method.

    > on other hand, using Runnables as custom control blocks like
    > the Releasable.do() suggested above would result in the
    > exception being thrown out of do() and into the code that
    > physically contains the block.


    This is an entirely different situation, and yes, that one does
    make sense. Such a custom block structure would most likely not
    take a Runnable, but rather a
    "HaroldsRunnable<ThisException,ThatException,...>" :)

    > * Allow array literals in expressions other than assignment RHS.

    I think there are a big lot of caveats that need to be dealt
    with. It starts, where the Compiler needs to know, just what
    is the Element-type. It can infer it in the "assignement-RHS"
    case, but not safely elsewhere.

    > * Have array constructors added to the collection classes:

    If the previous item has a solution, then this one can
    easily be done by appending .toList() to the array-literal.
    (leaving out the HashMap here, which is a different beast)

    > * Add java.lang.Pair<K, V>. Make some existing classes Pair
    > implementations, e.g. Dimension extends Pair<Integer, Integer>,
    > possibly also Rectangle extends Pair<Dimension, Dimension>,
    > Map.Entry<K,V> extends Pair<K,V>, etc.
    > Two-element array literals allowed where Pair is expected and
    > produce Pair literals.

    The Rectangle makes me feel uneasy about it. As a Pair of pairs,
    it probably could no longer directly access its own data, but
    would have to maintain two pointers to separate Dimension instances.
    But then again, I may be wrong...
    Is it possible to extend a class with two references, but implement
    it all inside the subclass, avoiding even the space wasted for
    the inherited fields? I don't think so.

    > * [int x]; defines a final box containing an int, an instance of a
    > Box<T> with T == Integer, which has methods T get() and void set(T).
    > One can then do e.g.
    > [JFrame foo = new JFrame()];
    > ...
    > SwingUtilities.invokeLater({foo.get().setVisible(true);});
    > given the above runnable-literal suggestion.
    > Add a : operator that expands to ".get()." and we have:
    > SwingUtilities.invokeLater({foo:setVisible(true);});
    > Almost a closure, there!

    But much yuckier syntax ... I don't see the gain at all.

    > * In many more cases it might be useful to have a shortcut to
    > if (x == null) value = this else value = that
    > so how about more generally allowing x.foo?ifNull -- the ? clause
    > is executed whenever x is null and the method call when it's not.
    > Or just allow x?expression1:expression2 for non-Booleans testing
    > for null.

    How would this behave with Boolean x= new Boolean(false); ? :)
    The object is not null, but means false (after auto-unboxing).

    > * Another source of boilerplate code is:
    > try {
    > Type t = someExpressionThatMayThrow();
    > } continue {
    > t.doSomething();
    > } catch (FooException e) {
    > ...
    > }

    I saw this discussed also in another language's group.
    (using different keywords, but to the same semantics)

    I do not see the usecase as all that common, myself.
    I wouldn't oppose it, either.

    Another entirely different approach could be an
    "exemptfromtry { ... }" block inside the try-block.
    That would allow for mixing catching and non-catching
    blocks inside the try, and thus have all non-exempted
    blocks inside the try guarded by the same catch-clauses.
    The Compiler would create several ranges to the exception-
    table, one for each part between two exemptfromtry's, all
    pointing to the same handler-bytecode address.
    Just a thought.

    > * Full closures.

    Quite a controversial topic.

    > * Object.identityHashCode().

    I could have sworn that I saw some static method of some
    utility class that returned the original hashCode for any
    instance. Probably some reflection thing. Anyway, wasn't
    able to find it now. Even if it doesn't exist, I think
    a static method in a reflection-related class would be a
    better approach, than adding it to Object.

    > * Equalizer to go with Comparator, provides equals and hashCode by
    > proxy, can be used with HashSet and HashMap to provide substitute
    > key equality and hash functions the way Comparator can provide a
    > substitute compareTo for TreeSet and TreeMap.

    Never so far found a need for that. Is there any which
    using a wrapper for the Key object cannot solve?
    Comparator mostly exists because not all classes are
    per se Comparable, but all classes are "Equalizable".

    > * WeakValueHashMap, LinkedWeakHashMap, and LinkedWeakValueHashMap.
    > These would all be useful implementing caches where you want the
    > mapping to go away if the value is no longer in use,

    So far it looks like WeakHashMap<Key,WeakReference<Value>>
    wrapped such as to transparently map the case of a nullified
    WeakRef to a "not found" condition.

    > WeakValueHashMap already sort-of exists in one under-the-hood bit
    > of non-user-reusable Java: the implementation of string interning,
    > starting whenever they finally got it to GC unused interned strings.


    Maybe they even do it with Soft- or WeakRefs.... Actually I wasn't
    really sure, that interned Strings really had a chance of being collected.

    > * ReferenceQueue.addListener(Reference r)

    Hooking into the GC has come up quite frequently here, and most likely
    it's a bad idea in the first place.

    > * Allow subclassing an enum with the subclasses able to REMOVE (not
    > add!) values. An enum that can be any of X, Y, or Z is a subtype,
    > rather than a supertype, of one that can be any of X, Y, Z, A, or B
    > because it is substitutable for the latter but not vice-versa;

    ok so far.

    > actual created classes would be Super with subclasses Sub, Super.A,
    > Super.B, Super.X, Super.Y, and Super.Z and subclasses of Sub Sub.X,
    > Sub.Y, and Sub.Z, with some change to the underlying code to not treat
    > Sub itself as an enum value for Super and to treat Sub.X, Sub.Y, and
    > Sub.Z as convertible to their Super counterparts.


    I don't get that at all. What Subclasses are you now talking about?
    Each instance of a given enum can be really one of an anonymous subclass
    of the enum, but needs not. In
    enum Foo { X, Y, Z}
    There is only one class-file: Foo.class. no Foo$X.class, ...

    The case I could imagine was a SubEnum, that allowed a free
    selection of a subset of BaseEnum's instances, and otherwise
    behaves like a wrapper based on my own class-wrapper proposal
    (messageid given in my comment to your second item).

    E.g.:
    enum Base { X, Y, Z { ... }; ... }
    enum Sub wrapspartsof Base {
    Y,Z;
    Sub foo() { return Z; } // ok, implicitly castable to Sub
    //Sub bar() { return X; } // would fail: X is not a Sub
    //private int count; // would fail: no extra fields allowed.
    }
    //Base.X.foo(); // fail: no such method.
    //Base.Y.foo(); // fail: no such method. (Compiler doesn't know
    implicitly, which of Base's possibly countless
    wrappers is meant here)
    Sub.Y.foo(); // ok, named as Sub.Y, it's of type Sub ...
    ((Sub)Base.Y).foo(); // ok, Compiler knows compatibility to Sub,
    so method foo() is known to be Sub.foo()
    Sub.Y.foo(); // ok,
    Base.X instanceof Sub // false
    Base.Y instanceof Sub // true!
    Sub.Y instanceof Sub // trivially true
    Sub.Y == Base.Y // true; it's still the same instance afterall.
    (all ditto with Z for Y)
    Sub sub=...; switch (sub) { case Y: ... case Z: ... } // ok, all cases handled.

    * Now finally, I add one more idea to the list:

    Distinguish between "using" and "implementing" an interface with
    respect to accessibility.
    The point being to allow to publish an (internal) interface
    for return values (cookies), that foreign code may use as type
    for variables, but not in "implements"-lists for classes.

    One use would be for a library to return "handle" objects
    from some of its methods, and accept these handles as parameters
    to other methods, allowing user-code to do well-defined
    tasks on these handles outside the library, but preventing
    foreign code from implementing own classes for that interface
    (and especially: possibly feeding those back to the library)
    There are of course other ways to achieve that, like keeping
    a WeakHashMap of valid handles, but that's far less elegant.
     
    Andreas Leitgeb, Oct 29, 2008
    #4
  5. Harold Yarmouth wrote:
    > * Provide a better way to deal with OutOfMemoryError or low memory in
    > general, as well as a JVM mode in which a program can use as much
    > memory as it needs, but the VM will also not greedily take everything
    > the OS will give it. In this, it may maintain a "load factor" similar
    > to a HashMap for the entire heap, trying to keep it near 75% full, and
    > a JVM option to tweak this may exist. Higher gives poorer GC
    > performance but leaves more RAM for the OS; lower gives better GC
    > performance but uses more memory; no value throws OOME unless the OS
    > won't give the Java process memory it needs.
    > Add System.addLowMemoryListener() or similarly. Listeners are notified
    > if free memory dips below some threshold, running on a temporary
    > worker thread and perhaps doing things like flush caches.


    On this topic in specific:

    The JVM has years of experience with tuning GC; the JVM's garbage
    collector (all 3 of them?) is one of the best out there. One lesson of
    the past few decades is that manual memory management is extremely
    difficult to get right; a garbage collector which has been worked on for
    over a decade is probably going to be managing its resources better than
    any custom scheme you come up with for your application.

    SoftReferences in particular are means of this: if you hold a
    SoftReference to an object, you are telling the garbage collector that
    you are willing to give up the reference if memory resources are getting
    low. Since it directly interfaces with the garbage collector, it is
    likely to be far more performant than listening for low memory and then
    flushing caches.

    Consider the case where some resource is consuming memory at a fast
    rate, e.g., downloading a large image over a fast connection.

    Under a SoftReference scheme, as the garbage collector notices that
    memory is getting tight, it will start finding and freeing the soft
    references when trying to allocate new memory.

    Under a listener scheme, these have to happen, in order:
    1. The GC will have to notice that memory is getting tight.
    2. The GC will have to tell the event dispatcher that memory is tight.
    3. The event dispatcher will have to callback the event listeners.
    4. The event listeners will have to free the caches.

    These are not happening on the same thread; in the right conditions, the
    GC will run out of memory before the event listener has the chance to
    free it.

    The memory usage of the JVM, etc., can be controlled from the command
    line with appropriate -X options; I don't know the degree of
    specificity, but I'm sure you can at least somewhat control the
    aggressiveness of reclaiming memory before requesting from the OS.

    In short: I'm sure the people who worked on the JVM GC are much more
    knowledgeable in the topic than you or I. Trying to outwit them will
    almost definitely result in failure.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
     
    Joshua Cranmer, Oct 29, 2008
    #5
  6. Joshua Cranmer wrote:
    > Harold Yarmouth wrote:
    >> There's probably plenty of these floating around already, but
    >> here's
    >> bits of mine:
    >>
    >> * Sort-of structural typing. Any object can be used where an
    >> interface type is expected if it has the right set of method
    >> signatures, whether or not it "implements" the interface using that
    >> keyword. (It still must to inherit constants defined in the
    >> interface, and methodless interfaces would not get this behavior
    >> else everything becomes, among other things, serializable!)

    >
    > I smell a lot of unexpected bugs coming from this. Note that if you
    > already have the right method signatures, you could just take the
    > interface onto the implements list.


    I see it as a maintenance nightmare. If methods are added to an
    interface, I'd like to be told about it when its implementors fail to
    compile, not when code which tries to use some other class as that
    interface fails to compile. The may be appropriate for Ruby, but not
    for Java.
     
    Mike Schilling, Oct 29, 2008
    #6
  7. Andreas Leitgeb wrote:
    > Harold Yarmouth <> wrote:


    >> * Allow extending final classes, subject to the constraint that new
    >> instance fields cannot be defined and none of the final class's
    >> methods
    >> can be overriden regardless of whether the method is explicitly
    >> "final". Essentially allows wrapping final classes.


    And also that the subclass can't call protected members.

    >
    > Yes, yes, yes! Not sure, if you got that idea yourself, or
    > from reading <>.
    > (in case google distorts it: "slrngfmc50.4jb.avl" is the part
    > before the "at")
    > As I brought it, it would subsume the functionality
    > of proposed typedefs plus add some more useful usecases.
     
    Mike Schilling, Oct 29, 2008
    #7
  8. Harold Yarmouth wrote:
    > * Allow extending final classes, subject to the constraint that new
    > instance fields cannot be defined and none of the final class's methods
    > can be overriden regardless of whether the method is explicitly "final".
    > Essentially allows wrapping final classes.

    As you wouldn't be able to override hashCode and equals the contract of
    these methods would be broken.

    > * Add some way to specify that something should never be null. Perhaps a
    > ! or a * before or after the variable name or type name.

    An annotation is being proposed to mark parameters etc as non null.

    Mark Thornton
     
    Mark Thornton, Oct 29, 2008
    #8
  9. Mike Schilling <> wrote:
    > Andreas Leitgeb wrote:
    >> Harold Yarmouth <> wrote:

    >
    >>> * Allow extending final classes, subject to the constraint that new
    >>> instance fields cannot be defined and none of the final class's
    >>> methods
    >>> can be overriden regardless of whether the method is explicitly
    >>> "final". Essentially allows wrapping final classes.

    > And also that the subclass can't call protected members.


    Indeed, except it is in the same package as the wrapped class :)
     
    Andreas Leitgeb, Oct 29, 2008
    #9
  10. Andreas Leitgeb wrote:
    > Mike Schilling <> wrote:
    >> Andreas Leitgeb wrote:
    >>> Harold Yarmouth <> wrote:

    >>
    >>>> * Allow extending final classes, subject to the constraint that
    >>>> new
    >>>> instance fields cannot be defined and none of the final class's
    >>>> methods
    >>>> can be overriden regardless of whether the method is explicitly
    >>>> "final". Essentially allows wrapping final classes.

    >> And also that the subclass can't call protected members.

    >
    > Indeed, except it is in the same package as the wrapped class :)


    Then you'd have the source code for the original class, and could
    comment out "final". :)
     
    Mike Schilling, Oct 29, 2008
    #10
  11. Mark Thornton <> wrote:
    > Harold Yarmouth wrote:
    >> * Allow extending final classes, subject to the constraint that new
    >> instance fields cannot be defined and none of the final class's methods
    >> can be overriden regardless of whether the method is explicitly "final".
    >> Essentially allows wrapping final classes.

    > As you wouldn't be able to override hashCode and equals the contract of
    > these methods would be broken.


    No it wouldn't. Just because the following things would be
    forbidden in such a wrapper class:

    * overriding of any methods (overloading still ok)
    * implementing any interfaces
    * adding non-static fields
    * accessing any members of the class, that any other
    class in the same package of the wrapper couldn't
    also access.

    (That should cover all things that could change the
    personality of an instance. I.e. things which could
    make a baseclass instance be distinguishable from a
    wrapper instance, (except for .getClass() and
    "instanceof wrapper") if wrapper were a normal subclass
    and both instances would be accessed from a baseclass
    typed reference.)

    The expression (new Wrapper()).getClass() would return
    the baseclass!

    Wrapper instances are exactly like baseclass instances, so
    baseclass instances can be treated like wrapper instances
    (and therefore be assigned to wrapper typed references).

    If the wrapped baseclass was not final, then you can even
    derive from a wrapper class, and that may override all
    methods of the wrapper and of the baseclass. That subclasses'
    instances are then implicitly castable to the direct wrapper
    and to the base class but not backwards. They are even
    implicitly castable to other wrappers and wrapper-wrappers
    of any class up the hierarchy tree! That's the transitivity
    of implicit castability.

    Instances of wrappersub would be different from instances
    of some plain subclass of baseclass, just like two sibling
    classes are per se different.

    e.g.: (quoted words are meta names used in for easier referral)
    HashMap<K,V> // "baseclass"
    class MyTypeMap<T> wraps HashMap<T,MyType> { // "wrapper"
    public synchronized MyType getAndSet(T key,MyType val) {
    gets and sets...
    }
    }
    class SubMap extends MyTypeMap<Integer> { // "wrappersub"
    public MyType getAndSet(Integer key,MyType val) {
    do some extra checks
    return super.getAndSet(key,val);
    }
    public MyType put(Integer k, MyType v) {
    do some checks
    return super.put(k,v);
    }
    }

    Wrappers can also be wrapped, but then neither the methods of
    baseclass nor of first wrapper may be overridden in the second
    wrapper.

    On a different subtopic:

    >> * Add some way to specify that something should never be null. Perhaps a
    >> ! or a * before or after the variable name or type name.

    > An annotation is being proposed to mark parameters etc as non null.

    Good news. Lets see how that works out.
     
    Andreas Leitgeb, Oct 29, 2008
    #11
  12. Mark Space <> wrote:
    >> * Allow extending final classes, subject to the constraint that new
    >> instance fields cannot be defined and none of the final class's methods

    > Feels yicky. Consider composition instead of inheritance.


    The way I proposed it a week or so back, the wrapper's instances
    would fulfill the "is a" relation even more strictly than a
    subclass' instance does.

    >> * Add some way to specify that something should never be null. Perhaps a
    >> ! or a * before or after the variable name or type name.

    > Does this require a runtime check on each assignment? Could be a lot of
    > overhead...

    I dislike the proposed syntax, but I'd expect it to work like
    generic types: The compiler knows them, and tkes care of them,
    such that casting a normal type to a non-null type would only
    work by branching away the null case:
    e.g. (with yucky syntax)
    Integer* nnIntRef=null; // fails to compile
    Integer intRef=...; Integer* nnIntRef=intRef; // fails

    Integer intRef=...;
    Integer* nnIntRef;
    if (intRef != null) { nnIntRef=intRef; } // ok.
    nnIntRef= (intRef==null)? 42 : intRef; // also ok.
    if (intRef == null) break; nnIntRef=intRef; // also ok.
    This does require some dataflow analysis by the compiler...

    >> * Disallow public constructors on abstract classes. They are not
    >> callable by any more code than a protected constructor anyway.

    > super();?

    That's equally ok with public and with protected, anyway.
     
    Andreas Leitgeb, Oct 30, 2008
    #12
  13. Harold Yarmouth

    Guest

    I wish they would stop adding features and concentrate on fixing bugs.
     
    , Oct 30, 2008
    #13
  14. Harold Yarmouth

    Mark Space Guest

    Andreas Leitgeb wrote:

    > Integer* nnIntRef=null; // fails to compile
    > Integer intRef=...; Integer* nnIntRef=intRef; // fails


    > This does require some dataflow analysis by the compiler...


    What about:

    Map<String,Integer> map = new HashMap<String,Integer>();
    nnIntRef = map.get("Blarg");


    >
    >>> * Disallow public constructors on abstract classes. They are not
    >>> callable by any more code than a protected constructor anyway.

    >> super();?

    > That's equally ok with public and with protected, anyway.
    >


    Right. I was thinking package-private instead of protected, for some
    reason. Carry on.
     
    Mark Space, Oct 30, 2008
    #14
  15. 16-bit and 128-bit binary float.
    32-bit, 64-bit, and 128-bit decimal float.


    --
    John W. Kennedy
    "Only an idiot fights a war on two fronts. Only the heir to the
    throne of the kingdom of idiots would fight a war on twelve fronts"
    -- J. Michael Straczynski. "Babylon 5", "Ceremonies of Light and Dark"
     
    John W Kennedy, Oct 30, 2008
    #15
  16. Mark Space <> wrote:
    > Andreas Leitgeb wrote:
    >> Integer* nnIntRef=null; // fails to compile
    >> Integer intRef=...; Integer* nnIntRef=intRef; // fails
    >> This does require some dataflow analysis by the compiler...

    > Map<String,Integer> map = new HashMap<String,Integer>();
    > nnIntRef = map.get("Blarg");


    It would fail of course. get returns a normal nullable Integer.
    If there were a throwing variant of get(), and if the valuetype was
    non-null Integer, then the returntype of that get() would be non-null
    integer und thus could be assigned to such a variable. Easy, innit?
     
    Andreas Leitgeb, Oct 30, 2008
    #16
  17. Harold Yarmouth

    Roedy Green Guest

    On Wed, 29 Oct 2008 04:56:14 -0400, Harold Yarmouth
    <> wrote, quoted or indirectly quoted
    someone who said :

    >* When a type has a one-argument plus() method, + can be used when the
    > left hand operand is of that type and the right hand operand is of an
    > argument type for which the former has a one-argument plus() method.
    > This + binds with the usual precedence for binary + and x + y is
    > simply an alternate way of saying x.plus(y



    Please NO. How about circle plus or some other additive symbol. You
    NEED to know if a plus is primitive or user defined.
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    A vote for McCain is fearful clinging to McSame.
    A vote for Obama is a shot at Obamalot.
     
    Roedy Green, Oct 30, 2008
    #17
  18. Harold Yarmouth

    Roedy Green Guest

    On Wed, 29 Oct 2008 04:56:14 -0400, Harold Yarmouth
    <> wrote, quoted or indirectly quoted
    someone who said :

    >
    >* Dead code in a method should be a warning, not an error.


    similarly a throws in a method that does not throw. It is part of the
    signature for future reference or to leave the option open in an
    override.
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    A vote for McCain is fearful clinging to McSame.
    A vote for Obama is a shot at Obamalot.
     
    Roedy Green, Oct 30, 2008
    #18
  19. Roedy Green wrote:
    > On Wed, 29 Oct 2008 04:56:14 -0400, Harold Yarmouth
    > <> wrote, quoted or indirectly quoted
    > someone who said :
    >
    >>
    >> * Dead code in a method should be a warning, not an error.

    >
    > similarly a throws in a method that does not throw. It is part of
    > the
    > signature for future reference or to leave the option open in an
    > override.


    That works fine now.

    import java.io.*;

    class Throws
    {
    void method() throws IOException
    {
    }
    }

    compiles with no errors (or even warnings) in 1.4. Perhaps you're
    thinking of trying to catch an impossible exception, e.g.

    import java.io.*;

    class Throws
    {
    void method() throws IOException
    {
    try
    {
    int i = 12;
    }
    catch (IOException ex)
    {
    }
    }
    }

    This does fail with

    Throws.java:11: exception java.io.IOException is never thrown in body
    of corresponding try statement
    catch (IOException ex)
    ^
    1 error
     
    Mike Schilling, Oct 30, 2008
    #19
  20. Joshua Cranmer wrote:
    > Harold Yarmouth wrote:
    >> There's probably plenty of these floating around already, but here's
    >> bits of mine:
    >>
    >> * Sort-of structural typing. Any object can be used where an interface
    >> type is expected if it has the right set of method signatures, whether
    >> or not it "implements" the interface using that keyword. (It still
    >> must to inherit constants defined in the interface, and methodless
    >> interfaces would not get this behavior else everything becomes, among
    >> other things, serializable!)

    >
    > I smell a lot of unexpected bugs coming from this.


    How so?

    > Note that if you already have the right method signatures, you could
    > just take the interface onto the implements list.


    Not if the class is not under your control for whatever reason.

    >> * Allow extending final classes, subject to the constraint that new
    >> instance fields cannot be defined and none of the final class's
    >> methods can be overriden regardless of whether the method is
    >> explicitly "final". Essentially allows wrapping final classes.

    >
    > No, essentially makes final classes worthless.


    Not true. It won't be possible, under that proposal, to break e.g.
    String by either changing the behavior for clients working with just
    "String", or Integer by e.g. creating a super-bloated subclass that will
    gum up the works and get stuck in the intertubes because it's so fat. :)

    I should add that nonpublic fields and methods would not be visible to
    the wrapper, unlike what's normally the case. (I mentioned that later in
    my post, but it seems to be missing from the above, oddly enough.)

    >> * Add some way to specify that something should never be null. Perhaps
    >> a ! or a * before or after the variable name or type name.

    >
    > How about adding a @NotNull annotation and then running your own static
    > checker?


    Awkward and clunky. More typing than a single punctuation mark, by a
    factor of eight -- nearly an order of magnitude. Doesn't "just work"
    like existing type-checking, but requires manually linting with some
    special tool that you'd first have to find someplace, install, and learn
    to use. And so forth.

    At minimum it would have to be checked by straight javac, as @Override
    is now. But even then, nearly an order of magnitude more typing? This
    would be used much more frequently than e.g. @Override, probably on a
    large minority of all field, variable, and parameter declarations, if
    not an actual majority.

    >> * When a type has a one-argument plus() method, + can be used when the
    >> left hand operand is of that type and the right hand operand is of an
    >> argument type for which the former has a one-argument plus() method.

    >
    > [ ... ]
    >
    > A poor way


    No, it is not, and I will thank you to stop gratuitously insulting me.
    You, sir, have an attitude problem.

    If you have nothing pleasant or constructive to say, might I suggest
    that you keep your mouth shut in the future?

    >> some others. <= and >= and < and > use compareTo. === and !== get
    >> added and use .equals, and bind with the same precedence as == and !=.

    >
    > Except many other languages use == as equivalent to the equals method
    > and === as equivalent to Java.


    Other languages are irrelevant.

    You aren't posting to discuss this, are you? You're just posting to shit
    all over it and generally be boorish. Shame on you.

    > Also note that you'll fall down with nulls here.


    That might require a special case, treating x === y as (x == null)?y ==
    null:x.equals(y) than just x.equals(y) perhaps.

    All the more reason for collapsing it to just a few characters, if you
    ask me.

    >> * Provide a better way to deal with OutOfMemoryError or low memory in
    >> general, as well as a JVM mode in which a program can use as much
    >> memory as it needs, but the VM will also not greedily take everything
    >> the OS will give it.

    >
    > Judicious use of WeakReference and SoftReference helps, and there are
    > also suitable APIs in java.lang.management that already provide much of
    > this functinoality.


    Java.lang.management is not covered by any of the tutorial or similar
    documentation that's out there, and is just one package buried in a list
    of literally hundreds in the API docs, so you'll forgive me for not
    being familiar with it.

    >> * Especially given the above: a shortcut for new Runnable() { public
    >> void run () { ... }}.

    >
    > [ ... ]
    >
    > I take it you haven't heard of closures.


    Sure I have. Did you even bother to read my entire post before clicking
    "Take A Crap All Over It And Send" in your news reader?

    >> * Allow array literals in expressions other than assignment RHS.
    >> Why the devil is foo(1, "string literal", 3) allowed but
    >> foo(1, {array, literal}, 3) is not, even when foo's second
    >> parameter type is Object?

    >
    > new Object[] {array, literal} ?


    Works, but if the array doesn't need to be modifiable, creates a
    wasteful duplicate every time.

    If you're worried that letting immutable arrays get used in such
    contexts could somehow cause problems, keep in mind that this is already
    possible:

    int[] foo = {1, 2, 3};
    ....
    fooMethod(1, foo, 3);

    >> * Have array constructors added to the collection classes:
    >> (with the above as well)
    >> new HashSet({2, 3, 5, 7, 11, 13});
    >> new ArrayList({"foo", "bar", "baz", "quux"});
    >> new HashMap({{"key1", "value1"}, {"key2", "value2"}});

    >
    > new HashSet(Arrays.asList(2, 3, 5, 7, 11, 13));
    >
    > So much cleaner IMO.


    You're joking, right? It makes an unnecessary temporary collection. In
    fact, all the collections really ought to have constructors that take an
    Iterable and just iterate over it. In many cases, they can be
    implemented in all of two lines of code:

    super();
    addAll(iterable);

    given that addAll gets broadened to allow any iterable. Or at least

    super()
    addAll(collection);

    > There's also this for the last one:
    > new HashMap() {{
    > this.put("key1", "value1");
    > this.put("key2", "value2");
    > }};


    Now you're making a whole extra class. How efficient.

    >> Or just allow x?expression1:expression2 for non-Booleans testing
    >> for null.

    >
    > x == null ? expr1 : expr2 is not at all verbose and much easier to
    > distinguish on scanning.


    It's slightly more verbose and no easier to scan for.

    >> * Full closures.

    >
    > Someone beat you to this.


    Now you've gone from "nonconstructive" to "just plain bloody-minded".

    >> * Allow subclassing an enum with the subclasses able to REMOVE (not
    >> add!) values.

    >
    > Very ugly.


    In your humble opinion.

    > Most of your features have little chance of being added


    In your humble opinion.

    > many of them would require making deep changes for what I see as
    > little value.


    Perhaps you should make an appointment with your optometrist, then. Many
    small wins add up to eventually equal some big ones.

    Please don't bother to write back until you have something genuinely
    constructive and useful to say. Slagging something without suggesting
    improvements (or slagging people, at all) is pointless and a waste of
    everybody's time.
     
    Harold Yarmouth, Oct 30, 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. Ville Vainio

    Wishlist item: itertools.flatten

    Ville Vainio, Mar 11, 2005, in forum: Python
    Replies:
    19
    Views:
    665
    Christos TZOTZIOY Georgiou
    Mar 17, 2005
  2. Steven Bethard
    Replies:
    0
    Views:
    406
    Steven Bethard
    Mar 12, 2005
  3. Laszlo Nagy
    Replies:
    1
    Views:
    262
    Stefan Behnel
    Jul 11, 2006
  4. NiTiN
    Replies:
    4
    Views:
    303
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Dec 29, 2006
  5. newby2c

    K&R Wishlist

    newby2c, Sep 29, 2005, in forum: C Programming
    Replies:
    83
    Views:
    1,800
    Corrupted Mind
    Oct 14, 2005
Loading...

Share This Page