Forum Stats

  • 3,872,124 Users
  • 2,266,390 Discussions
  • 7,911,052 Comments

Discussions

Generic solution

843793
843793 Member Posts: 41,732 Green Ribbon
edited Jul 29, 2002 11:32AM in Generics
If I template a class it will replace the interface of that class such that I dont have to cast what goes in and out of the class anymore because the new class will accept the true object type in the raw. This is not the same as wrapping the class because a wrapped class just has its casts on the inside. Generics MUST eliminate all typecasting.

Collections will have to be written from the bottom up as template classes which will have to be essentially abstract because they can not be compiled without knowing what types of objects to use.

This should speed up code and make it more safe by removing all of the typecasting.

But my question is now what is the contract or relationship between my templated class and the class it was templated from? The template class of course will never exist as a .class file.

Technically wouldnt a generic generation tool be more appropriate? Like we have the IDL tool? Make generic classes a .gen file and make them require processing through another tool that will simply generate java source code in a consistent fashion. Since this is all compile time, this would be a perfect solution especially since the debugger would be able to step through the source and the class cleanly.

I think this has to be better and the least invasive of the options. letting people create and manage their own generic classes and also sun can supply generic collections too.

advantages.

1. no javac changes.
2. no JVM changes.
3. no changes to appearance of source code for developers who review code they didnt write.
4. The generic class is there and ready to generate new .java files at your discretion.
5. Completely optional. a user does not even have to know they exist.

Anyone have a problem with this? Did I miss the point?
«134

Comments

  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    Did I miss the point?
    Yes, you have missed the point entirely. I'll try to answer your points without bursting into flame-bait, but you really have utterly misunderstood the way Java's generics will work.

    C++'s templates were a very bad implementation of generics. They created at compile-time a version of the class for each type they were to be used by. When you used a template with a new parameter, it created a new version of the template class to support it.

    Java's generics are very different from C++ templates.
    Yes, the syntax looks similar, but don't let that decieve you. A generic class in Java (they aren't even called templates) is compiled into a single class. List<Integer> is the same class as List<Clonable> and List itself. There are no extra classes created.

    There is no pre-processor involved, because there are no extra classes to generate, no extra code to be written.

    The bytecode will match the source just as well as it does today (which is to say, reasonably well).

    The JVM doesn't need to change to accomodate this, and code written using generics will happily run in pre-generic JVMs. Most of the checking of generics will happen at compile-time. As such, a lot of the generic information is thrown away before it produces a .class file. The format for .class files is unchanged.

    Generics won't eliminate every single cast from Java, and neither will any other magic bullet, but using them correctly will eliminate a very large number. I estimate that about 90% of the casts in my code will vanish when it becomes generic.

    Generics are completely optional. If you wish, you can ignore the generic aspect of collections. You are free to create a List, without having to specify that it is a List<Object>. Existing code will compile happily on the generic compiler, no changes are necessary.

    And best of all, you can use the compiled generic class with new types of parameter, and it won't have to create any new classes to handle them.

    Do you see now? Your whole understanding of generics was completely wrong. I hope I managed to set you straight.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    I dont see how you can have a class which essentially will accept "Object", which is your generic class. Then mask it over with a new class that will delegate its calls to the original class and also will only accept a certain class. In this case their would be lots of typecasting by the programmer, but not the user. If your going to do runtime casting then you have really just saved a bunch of typing but not added anything real as far as I can see.


    How are they avoiding runtime type casting with this system?
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    How are they avoiding runtime type casting with this
    system?
    The fact is, they don't. Generics are a compile-time tool, that reduce the need for explicit casts in your code. They help you to catch far more of the type errors when you compile, because you aren't casting by hand.

    Instead, it adds casts when it compiles - but only casts that it can prove to be correct. That means that there are just as many casts at runtime, but that the casts cannot fail, because the wrong thing will never be there.

    What you have added is a better understanding of the type system, and the ability to catch more bugs before they get through the compiler.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    How are they avoiding runtime type casting with
    this
    system?
    The fact is, they don't. Generics are a compile-time
    tool, that reduce the need for explicit casts in your
    code. They help you to catch far more of the type
    errors when you compile, because you aren't casting by
    hand.
    I fail to see the need for a code helper as part of a language specification.
    Instead, it adds casts when it compiles - but only
    casts that it can prove to be correct. That means
    that there are just as many casts at runtime, but that
    the casts cannot fail, because the wrong thing will
    never be there.
    I can do this myself.
    What you have added is a better understanding of the
    type system, and the ability to catch more bugs before
    they get through the compiler.
    I dont see that anything of value has been added. In fact its just another thing to learn and in the end, it does not do anything which can not be done currently. It saves typing, that is "keystrokes". But it does not save casting and thus provides nothing tangible.

    The tool I propose would save keystrokes as well as eliminate typecasting alltogether in this respect. However, it would produce larger executables.

    I don't mean any offence, I just expected Generics to actually do something which could not currently be done, but they are essentially just a simple pre-processor as proposed.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    I can do this myself
    You're correct. You can:
    - write well-packaged C that packages the functions dealing with a particular type of struct in the same place.
    - use manual pointer counting to keep track of the number of times each struct is referred to, and delete it when it isn't.
    - keep a large table in memory that maps method identifiers to function pointers dynamically whenever you need to call one of them.
    - scatter your programs with lots of groups of booleans, and call functions to set and clear them whenever you need to gain or release access to certain resources
    - keep internal type variables on list structures, and check all incoming and outgoing values to make sure that only the correct type gets passed in or out.

    All that does work, and people have successfully written programs using it. But some of us would rather not do all that work - we'd rather let our computers do it for us, by providing:
    - objects and classes
    - garbace collection
    - polymorphism
    - synchronization
    - and generic programming.

    Both methods work, but the advantages of doing all that lot at the language level are:
    - catch errors as soon as you compile, not after the program has been shipped.
    - save not just on typing, but also on thinking the same thing again and again, freeing up small brain to think about other areas of the program.
    - allow the program to optimize code a lot more efficiently than I am humanly capable of.

    And if you think those examples above are silly, consider that I didn't even get near to the accursed GOTO, or issues of platform independence.

    At this point you're probably about to post something like: "That's not what I said!" But listen.

    Generic programming takes the language to a higher level of understanding, by allowing you to state more clearly what it is that you intend to do (such as what a collection contains). Once the compiler knows about it, it can make sure that your code doesn't break these constraints. No longer does the person have to do casting with collections themselves - the compiler does it for them, and it always does it correctly. You, the programmer, are then free to think about other things.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    First, this is not a language level idea. The proposals I saw made no changes to the JVM except the last one. Since this can be done in code, its not about making anything safer, like most of those points you posted were, its about making coding easier. Java does not just allow you to write safer code like c++, it mandates it on the language level. But this is not about safe code. This is about time saving.

    In fairness, if this existed I would have used it many times by now already, and would keep using it. I suppose I can see no reason not to use it if it were available.

    I see the benefit of it, and the benefit is time saving. Thats all. Maybe thats enough, but when I see people post things about typesafety and such, I have to disagree.

    Yes, I guess I agree with you. I understand it now, and its not that huge deal people are saying it is, and its not about any safety but maybe if I were a company and it would save all this time I would feel different.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    You save time, but you also save trouble. Without enforcing the correct type of a container, it's possible to ship a program with a rare, hidden bug. To my mind, that's what typesafety means.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    OK, I guess you can say safety is forced though I don't completely agree.

    How will the Template class keep from exposing its methods? Declare them protected? Todays collection classes can not be used as a base class because the extension act itself will leave the get and set Object methods exposed.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    I, too, am in favor of a C++ style template, which substitute types at compile time. The reason is that most of my program handles primative types, converting between primatives and objects takes time, and uses more memories, which is critical for me, as the top priority of my apps are performance (without using too much memory). In my apps, even using 'int' or 'long' as generic integer is not acceptable, as I'm handling up to hundered millions integers which using 'byte' could save lots of memory usage. I could implement a set of 'Collection' classes for each primative type, however, it still takes lots time, and write the same logic again and again and again and again. I really want something like:
    HashMap<short, String> map = new HashMap();
    so that millions operations of
    map.put(5, "Value 5");
    could save lots of memory and CPU times compare with
    map.put(new Short(5), "Value 5");

    I understand the benifit of Java's new Generic framework, and the downside of C++'s template, but C++'s template some times really helps.
  • 843793
    843793 Member Posts: 41,732 Green Ribbon
    dnoyeB: Are you making fun of us?
    I once thought, that you simply didn't care to read the specification
    because it's more fun to post to the forum (even without any idea what
    you are talking about).
    But you keep missing the point of every single answer, so now I guess
    you are simply laughing your a** off about everyone who is so dumb to
    answer...

    If you really mean what you write, here are some tips:
    Language Level means Java, compiled code is something different
    altogether. You should not (and should never need to) care about what
    constructs of virtual machine code the compiler generates. (Unless you
    are writing a compiler/decompiler/obfuscator/...)
    If you can't write any JAVA code that causes the dynamic casts to
    fail, then at language level there are no casts involved.
    Learn that inheritance should always represent an "is-a"-relationship.
    So you should not really extend any collection class, unless your new
    class really is a specialisation of the collection class, in which case
    there are no methods to be hidden. This has absolutly nothing to do with
    genericity.
    Read the spec. Try to understand it. Read it again.

    C++ templates can be useful, but they always tend to become a nightmare.
    They are rarely portable (the C++ spec is much too loose about where and
    when to instantiate a template). (Not to mention that almost no compiler
    implements all template features, e.g. member function templates or
    partial template instantiation.) You cannot separate interface and
    definition: For exactly the reason that the template isn't exactly a
    class, but rather a blueprint that tells how to instantiate a class.
    So a C++ template is much more preprocessor-like as the Java
    implementation.

    -

    The issue of primitive types is something different altogether and as I
    see it, there has been a lot of discussion about it.
    Personally I think there shouldn't have been primitive types in Java at
    all. Java implementations could instead have been streamlined for fast
    execution of the Integer, Double, ... types. (Like the tricks that are
    used in many Smalltalk implementations.)

    The problem as I see it is, that the idea of primitives as template
    arguments isn't feasible when you want to have one template class
    represented by exactly one implementation. There is no super-'class'
    type to all primitive types (like there is Object for all classes) that
    can take the place of the template argument in the class's byte code and
    can be later dynamically cast to the appropriate type.

This discussion has been closed.