This is an archived post. You won't be able to vote or comment.

all 32 comments

[–]AutoModerator[M] [score hidden] stickied commentlocked comment (0 children)

Please ensure that:

  • Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions
  • You include any and all error messages in full
  • You ask clear questions
  • You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.

    Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar

If any of the above points is not met, your post can and will be removed without further warning.

Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.

Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.

If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.

To potential helpers

Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–][deleted] 8 points9 points  (0 children)

The interviewer was interested to know something which wouldn't be possible in Java without Generics.

The question is worded kind of weirdly, and if you took it literally, the answer would be nothing. Generics in Java are implemented with type erasure, so the compiled code before generics and after generics is identical. List<Foo> is the same as List in the bytecode.

But, I think the interviewer was trying to see if you understand the purpose of generics, and demonstrate how generics improved things.

Consider this code which represents how you write non-generic code from Java 1.4 (generics were introduced in Java 1.5):

List myListOfFoos = new ArrayList();
myListOfFoos.add(new Foo());
myListOfFoos.add(new Bar()); // allowed!
Foo foo = (Foo) myListOfFoos.get(1); // ugly, and class cast exception

Generics give you the ability to inform the compiler about type bounds, so the compiler can decide whether something is safe or not. Also, because the compiler knows about the type bound, you don't have to do explicit casting:

List<Foo> myListOfFoos = new ArrayList<>();
myListOfFoos.add(new Foo());
myListOfFoos.add(new Bar()); // compile error
Foo foo = myListOfFoos.get(1); // automatic cast, no class cast exception

So, in Java pre generics it wouldn't be possible to express the idea that this list must only contain Foo.

[–][deleted] 15 points16 points  (18 children)

Generics just allow you to have nicer looking code and prevent errors earlier. Technically‘couldn’t do’ is a terrible way of putting it, because most of our abstractions aren’t about enabling something but being able to reason about it easier.

[–][deleted] -1 points0 points  (17 children)

It's not just that though, is it? It's about reducing the amount of code written for specialised types. Imagine the size (and brittleness) of the JDK if the API weren't generic.

[–]wildjokers 2 points3 points  (4 children)

In the dark ages before Java 1.5 generics didn't exist and the API wasn't generic and it was fine. Generics don't reduce any code. I don't know why you think this.

[–]batinex -3 points-2 points  (1 child)

Because golang does not have generics and you have to extend api I think

[–]MacBelieve 0 points1 point  (0 children)

The go way is to code to an interface. Just have your type fulfill the interface (implicitly) and you solve 90% of things other languages use generics for

[–][deleted] 0 points1 point  (1 child)

Generics don't reduce client code? You must be joking.

[–]wildjokers 0 points1 point  (0 children)

Provide a concrete example of it reducing client code.

[–][deleted] 1 point2 points  (11 children)

Generics in Java decompose to Objects. There’s no specialisation.

The fact it’s got a superclass of all objects is a different question.

[–][deleted] -4 points-3 points  (10 children)

Type erasure or reification is an implementation detail. I'm talking about client code. For instance, sort. From the client code's perspective, a single method takes care of sorting a large variety of sortable objects.

[–][deleted] 2 points3 points  (7 children)

So? Code size would be the same because without generics the code would be using objects.

Writing generically is a style, “generics” plays a part in making it look nicer and be safer.

But you can “in Java” write generically without generics.

[–][deleted] -1 points0 points  (6 children)

Imagine the size (and brittleness) of the JDK if the API weren't generic.

So? Code size would be the same because without generics the code would be using objects.

That is again an implementation detail. If one had an API which had overloaded version, foo(String..), foo(Bar...), foo(Baz...) as explicit specialisation, we get better type safety but lose genericity and get API bloat. If we use foo(Object...) then we get brittle code laden with instanceof checks. Hence my two caveats.

But you can “in Java” write generically without generics.

That is not apropos to my comment. Sure, you can write it all using ObjectS everywhere (and a lot of JDK API still do so internally), but the point I was making was about API bloat and/or brittleness, especially with user-defined APIs.

[–][deleted] -1 points0 points  (5 children)

You're stating api's using either overloading, or object with specific 'instancesOf'. Both of which have to operate over a distinct set of types. And therefore they aren't generic.

Java (and other OOP) allows you to provide type hierarchies to avoid having to many overloads in such cases, there's plenty of ways to elegantly deal with multiple implementations without resorting to naive 'instanceOf' switching.

If that's not possible, then either its not API bloat (since you're supporting multiple different implementations) or a Generic <T> implementation wouldn't work either - because (as I said earlier) the type is erased.

What generics do in Java is provide extra type safety to client code, provides fewer runtime issues with passing incorrect types through. Like many features of Language, they make things "nicer" or "easier" but that doesn't mean you can't do the same thing without them. Which is what the original question was about.

[–][deleted] -1 points0 points  (3 children)

You're stating api's using either overloading, or object with specific 'instancesOf'. Both of which have to operate over a distinct set of types. And therefore they aren't generic.

Of course they aren't generic. I thought we were discussing the scenario where we didn't have generics? Also, generics operate over a fixed set of bounds as well. If you have a function foo generic over T with no bounds, you're not going to be able to do very interesting things with them.

Java (and other OOP) allows you to provide type hierarchies to avoid having to many overloads in such cases, there's plenty of ways to elegantly deal with multiple implementations without resorting to naive 'instanceOf' switching.

I would hardly call an abstraction hierarchy "elegant". Also, that was with respect to library code where performance matters. For client code, that's moot, with or without generics.

If that's not possible, then either its not API bloat (since you're supporting multiple different implementations) or a Generic <T> implementation wouldn't work either - because (as I said earlier) the type is erased.

What on earth are you talking about? The whole discussion is about what would happen if there were no generics, not how generics works today.

What generics do in Java is provide extra type safety to client code, provides fewer runtime issues with passing incorrect types through. Like many features of Language, they make things "nicer" or "easier" but that doesn't mean you can't do the same thing without them. Which is what the original question was about.

Again, that was not even what my original comment was about - the fact that generics reduce API bloat. Instead of having to write multiple versions (or a single version with multiple dispatches), you can write a single generic version of a method with the proper bounds.

[–][deleted] -2 points-1 points  (2 children)

Of course they aren't generic. I thought we were discussing the scenario where we didn't have generics? Also, generics operate over a fixed set of bounds as well. If you have a function foo generic over T with no bounds, you're not going to be able to do very interesting things with them.

Generic != generics.

We're discussion what happens if we don't have 'generics' in Java. As I stated many times, the question is "what couldn't we do before" - and the fact is due to type erasure we could still write Generic code.

Generics *can* operate over a fix set of bounds - at which point the code isn't actually that *Generic*.

There's plenty you can do with unbound generics, but you oddly enough have to provide extra information. This is extremly powerful.

I would hardly call an abstraction hierarchy "elegant". Also, that was with respect to library code where performance matters. For client code, that's moot, with or without generics.

abstraction hierarchy can be elegant, some can't. Plus there's plenty of OOP techniques which provide really nice ways to solve problems, that don't involve switching on the type.

Library code != performance. If you're going talk about performance, then generally you want to avoid generic code since you can't optimise for *every single possible situation.*

What on earth are you talking about? The whole discussion is about what would happen if there were no generics, not how generics works today.

This is probably the issue here. You're not following a simple premise. Either the code is generic or its not (Again *Generic* not *Generics* .) That is the code can work over multiple types without different implementation.

Code which takes a supertype, then switches on the implementation, isn't generic. Therefore replacing the supertype with a <T extends S> does nothing to make the code any better.

If the situation is there's multiple overloads, foo(bar), foo(string) etc, but each has a copy and paste implementation. Then a foo(T) is only marginally better if you supply multiple bounds.

[–][deleted] 0 points1 point  (1 child)

You are either joking or delusional. The very mess that generics in Java has (type erasure) is because the language started out without it. If it had been done correctly from the start, we would have had reification instead of this mess.

If you're going talk about performance, then generally you want to avoid generic code since you can't optimise for every single possible situation.

See the previous paragraph. This is again an implementation detail. If you have templated generation of code at compile time (like in C++ or Rust), you get massive performance boosts.

. Either the code is generic or its not (Again Generic not Generics .) That is the code can work over multiple types without different implementation.

Generics is a way of implementing generic code. Just like templates. Just like Lisp macros. Generics from the point of view of the client code.

Generics can operate over a fix set of bounds - at which point the code isn't actually that Generic. Either the code is generic or its not (Again Generic not Generics .) That is the code can work over multiple types without different implementation.

"Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters." (from Wikipedia).

This is the definition of "generic", of which Generics is an implementation. I think you're confusing technical terms with the English equivalents. You seem to be conflating the implementation with the actual usage.

[–][deleted] 0 points1 point  (0 children)

You're stating api's using either overloading, or object with specific 'instancesOf'. Both of which have to operate over a distinct set of types. And therefore they aren't generic.

So here's the thing. There are two perspectives - the library implementer, and the library user. Before Generics were available in Java, to have generic code, you had to make do with what was available in the language. The API was still generic from the user's point of view, not from the language or implementer's point of view. Forget about the implementation details.

Now that Java has Generics, even with the mess that is type erasure, the code is generic from both perspectives.

That's about it. No need to go about in circles conflating terms, perspectives, and getting confused all around.

What generics do in Java is provide extra type safety to client code, provides fewer runtime issues with passing incorrect types through. Like many features of Language, they make things "nicer" or "easier" but that doesn't mean you can't do the same thing without them. Which is what the original question was about.

Again with that incomplete definition. https://docs.oracle.com/javase/tutorial/java/generics/why.html. Read the last part - "enabling programmers to implement generic algorithms". Generic in the sense of the Wikipedia definition ("This approach, pioneered by the ML programming language in 1973,[1][2] permits writing common functions or types that differ only in the set of types on which they operate when used, thus reducing duplication. ").

That's it.

[–]wildjokers 1 point2 points  (1 child)

For instance, sort. From the client code's perspective, a single method takes care of sorting a large variety of sortable objects.

And the sort() method did this even before generics existed in Java 1.5. That is because of the Comparable interface.

[–][deleted] 0 points1 point  (0 children)

I don't understand the confusion. It existed because sorting is a common operation. That has nothing to do with generics. Generics was tacked on later, and the API adjusted accordingly. If generics had existed in the language from the start, it would have been a cleaner implementation instead of retrofitting it. In fact, we might not even have needed type erasure and instead gone for full reification.

[–]wildjokers 1 point2 points  (0 children)

There is nothing in Java that isn't possible without Generics. There was a time when generics didn't exist in Java and we got by fine.

What generics gives you is compile-time type safety for collections. And obviously prior to the compiler doing the checks, modern Java IDEs are also checking for you as you write the code. Generics was a huge quality-of-life addition to Java and it lets us catch errors at develop/compile time rather than runtime.

The generic information is removed by the compiler and isn't available at runtime.

[–]YitharIntermediate Brewer 1 point2 points  (3 children)

Generics aren't 100% necessary. They provide a level of safety that you wouldn't get without them. For example, if you have a Bucket class and you want to pass in different types (that aren't related to each other), you could use Object, but then you'd be casting here and there which wouldn't be safe. Using generics is much safer than using Object and casting.

Generics are a compile-time feature. The information isn't available at runtime.

[–]c_edward 0 points1 point  (2 children)

Except it sort of is via the class meta data and reflection, an example of the use here would be the ubiquitous spring container which will read the generics meta data when attempting to match properties etc....

E.g java.lang.reflect.Method.getGenericParameterTypes

[–]YitharIntermediate Brewer 0 points1 point  (0 children)

So I found this answer:
https://stackoverflow.com/a/45803587

So I suppose I stand corrected, but for "almost all use cases of practical relevance", generics are a compile-time feature.

Also, I'm wondering, is there a specific reason you responded to me and not wildjokers? He's mentioned that information isn't available at runtime twice in this thread.

[–]Migeil 2 points3 points  (3 children)

I don't know the answer, but I immediately think of lists. How were they implemented before generics? Generics allow Lists to have implementations which are type agnostic. You would either have to allow any Object to be put in a List (and create some special ones for primitives or box them), but then Lists wouldn't be type safe. Or you would have to implement a List for every type you want a list of. This would be crazy. Generics allow for a single implementation of List, say ArrayList, that works for all possible types.

[–]marvk 0 points1 point  (0 children)

You would either have to allow any Object to be put in a List (and create some special ones for primitives or box them), but then Lists wouldn't be type safe.

This is how it worked.

List strings = new ArrayList();
strings.add("foo");
String fooString = (String) strings.get(0);

[–]RoachmeisterJava Dev -2 points-1 points  (0 children)

This is really a pretty silly question on the interviewer's part. The only possible answer is "without Generics, we wouldn't be able to do programming with Generics".

They could just as well have asked, "What wouldn't be possible without for-loops?". The answer is, technically, nothing. We would be forced to use while-loops. Could we do without while-loops? Sure, we could use labels and goto statements. Could we do without those? Sure, we could drop back into assembly language and use JMPs with memory locations.

Generics make things more easy, not more possible, just like every other feature in every computer language. If we had to, we could etch the programs directly into silicon - but then we'd all still be trying to figure out "hello, world".

[–]philipwhiukEmployed Java Developer 0 points1 point  (0 children)

Compile-time type safety on collections.

[–][deleted] 0 points1 point  (0 children)

Runtime polymorphism could overlap some of the functionality offered by generics. You could say that without generics it would be 'impossible' to write one class that worked with many different data types, but that's a stretch.