Things you disagree with in the java language

I was just thinking of this, because of a design decision i find to be absolutely wrongheaded;

I tried to use varargs, because i really really want to make my functions take one or many without having to deal with converting to a list on the case of ‘one’, and besides i often have to convert.

So i tried varargs. Then i had the problem of ‘conversion’ or ‘mapping’ (functional lingo). And then i had the problem that as varargs uses arrays it needs to have the non-generic class type (arrays being covariant and all).

What i’d really like is that varargs created a iterable that could then be easily wrapped in another iterable that could do the mapping (with lambdas or whatever). However due to the fact that arrays are covariant and not lazy i need to pass a collection (for the size()), a class (to instantiate the array) and the factory ‘lambda’) and waste time and space copying.
I’ve reached the conclusion that varargs do more harm than good in cases where you need to transform one-or-many into the function arguments expected, and that it’s better to do ‘asList’ on the function arguments that are not on collection form and pass a iterable.

Varargs was implemented targeting the wrong type and is almost completely useless!

Have you got any other pet issues?

[quote]And then i had the problem that as varargs uses arrays it needs to have the non-generic class type (arrays being covariant and all).
[/quote]
You can use generics:

	public static <T extends Component> void foo(T ... args) {
		for (T comp : args) {
			comp.invalidate()
		}
	}

I don’t see how asList is any better… Why do you need collections and size() when you can just use args.length? Maybe you could explain your issue with some code samples?

Funny enough, the asList method is a perfect example of using varargs.

You can use generics:

	public static <T extends Component> void foo(T ... args) {
		for (T comp : args) {
			comp.invalidate()
		}
	}

[/quote]
Try doing that with a method that takes a collection/array of generic type and returns a array of another generic type (ommit the factory function for the purpose of example). This to be used in a function that takes varargs arrays as a conversion step.

for a iterable argument…

    public static <E, T> Iterable<E> iterable(final Iterable<T> it, final Factory<E, T> factory) {
        return new Iterable<E>() {
            @Override
            public Iterator<E> iterator() {
                final Iterator<T> itr = it.iterator();
                return new Iterator<E>() {
                    @Override
                    public boolean hasNext() {
                        return itr.hasNext();
                    }

                    @Override
                    public E next() {
                        try {
                            return factory.create(itr.next());
                        } catch (Exception ex) {
                            throw new AssertionError("factory method shouldn't throw a exception when used in iterator", ex);
                        }
                    }

                    @Override
                    public void remove() {
                        itr.remove();
                    }
                };
            }
        };
    }

for a varargs argument…

    public static <E, T> E[] map(final Collection<T> it, Class<E> classE, final Factory<E, T> factory) {
        E[] out = (E[]) Array.newInstance(classE, it.size());
        int i = 0;
        
            for (T o : it) {
                try {
                  out[i++] = factory.create(o);
                } catch (Exception ex) {
                throw new AssertionError(ex);
                }
            }

        return out;
    }

See the additional class argument, narrowed collection interface, allocation, reflection and copy there? All because [] is not able to be lazy.
Varargs blow. There is nothing that they do currently that couldn’t have been done better by making their runtime type be a iterable instead of a array except modification of the runtime array argument which i never do and it’s filthy coding anyway (that remove() is bad too, assuming that it’s only to be used for argument transformation).
It’s no accident that the most used varargs method in the jdk is something that turns it into a iterable i guess (‘immutable list’) - especially with lambdas around the corner i’d advice to cut off varargs from your api’s.

Sounds to me like you’re hating varargs because Java isn’t a functional language. If you want lazy sequences, use Haskell.

My biggest gripe with java is that primitves shouldn’t exist. I hate the int/Integer (et al) pairing. There’s no reason why the language couldn’t have had ‘primitives’ as objects, e.g.: 12.toString();

Given that anonymous inner classes is a common Java idiom, Lambdas would have made that better and more flexible if that had been available from the outset.

System.out.println(blalalala);

I don’t mind primitives, it was just a nice feature to make it comfortable for C/C++ programmers to switch to Java (including myself). Its autoboxing that is the real sucker to hate. How many times have I had the following situation:

  • something blows in production
  • I check the log, see line 1546 of sourcefile X
  • check ling 1546 of sourcefile X, it is:

1545: entity.setOrderId(modelObject.getOrderId());
1546: entity.setStatus(modelObject.getStatus()); // crash? WHY?

modelObject cannot be null because line 1545 did not produce an error, there is nothing on that line that can produce an NPE! … Yeah, unless the status of the entity is a primitive and the status of the modelObject is an object which just happens to be null… DOH.

WTF? :o Why would you even write that? I’m assuming entity status is an int, in which case modelObject status is an Integer? Why would you mix and match different representations of status at all? And, most of the time surely an enum would be better?

WRT: Using real primitives was a good choice IMHO. From my perspective primitive wrapper classes should have come in mutable and non-mutable forms from the start. And mutable primitives wrappers should just have ‘worked’ as if they were, well, primitives. Note however, that this implies operator overloading. I really like pure object oriented (class and prototype based) languages. I sure they moved away from Self because it would simply been way too expensive (engineering wise) to make something reasonable fast within time and budget constraints.

A time/budget constraint thing I hate is: type erasure (die! die! die!)

Another thing I hate is per object locks. (WTF!!!???) Really bad idea then, horrible idea now and burdens every single object with extra (useless) memory overhead. (die! die! die!)

Minor: identity hashing. Again burdens all object with extra bit(s) and all which have ever called identity hash to be either pinned or potential expand memory-wise to store…just an implementation pain for little usefulness. Object’s hashCode should have just thrown an exception…done.

I really wish Java had proper built-in support for defining primitives/objects as immutable or not. A bit like C++'s const but better. Immutable classes or interfaces are a nice workaround but it’d be much nicer built into the language.

I believe Scala has something like this, but haven’t played around with that much.

Primitives were an excellent idea. It allows Java to get close to “the metal” when you need it to be. At the end of the day in Java you can actually write code that’s fast by design explicitly rather than having to hope it’s not doing something stupid under the hood. Mostly.

wrt per-object locking: I think it’s a great idea. It costs 2 bits* of information for most objects, which is hidden away in the object header and thus effectively free. Only contended locks need to escalate into a bigger structure.

Cas :slight_smile:

  • I think. Someone correct me.

Two bits sounds correct: https://wikis.oracle.com/display/HotSpotInternals/Synchronization agrees with that.

I keep missing the ability to handle memory (pointers) more directly. I understand why it is limited, but miss it nonetheless.

Yes, lack structures and array of structures is actually a very large problem. If we open the discussion to missing features, rather than issues with existing…my list would be longish…but that’s one of the biggest IMHO. There’s tons of related items here like cache-hints and SIMD access.

A list of C++ things I hate would be really long.
Fact is in java, most things you dont like you can ignore.

Although I too would like to explicitly define pointers…

In what way and for what purpose?

Actually very little of the things I dislike about Java are things that I can ignore. Sadly I must sometime dismiss Java as a viable option.

The only thing I miss as a feature in java is something like a “template”
[Edit: I hit “Tab” and “Enter”… accedently]
, as an extension to Generics. So you are able to put primitive types as generics…

So you can make an implementation of “Vec3” (Often brought by me as an example), to be able to cooperate with every “type of number”.
You can now use Vec3 Vec3 and even Vec3 for colors.

I like both Java and C++, each have their positives and negatives. And of course, you could argue that through JNI you can get both… but I digress.

Another thing I often miss in Java is, oddly enough, having to define headers (data structure / function prototyes). It is a hassle, yes, but helps tremendously to reduce code bloating and disorganization as a project grows.

As for why use pointers, function pointers are something I miss a lot (Maybe I’m missing something).
I’m not too fond of the limitations on multiple inheritance and on how interfaces work either.

Well in what way would be the C++ way:
Object* somePointer = Something.getObject();

Why ? Well sometimes it is unclear if something hold an object alone or is just a pointer. Of course in java everything is just a pointer.

But I had cases in which I did someObject = new Object() , not knowing that someObject was just pointing to something and that I would need to remove / recreate that, leaving me with 2 separate instances…

Good Code design can help to avoid these problems but most of the time a variable either holds an actual object/value or a pointer… in my code it doesnt happen that these behaviors switch…

I miss goto.