1 2 Previous Next 15 Replies Latest reply: Jun 4, 2011 8:07 AM by EJP RSS

    How To simplied Code Pattern in Generics?

    866364
      Hi All,

      An issue is met on Generics and java.lang.Number subclasses. It seems to be MORE of a API design
      method pattern that cannot 'join' nicely with Generics Syntax rather than a Generic Syntax Issue.

      To explain the issue, a simple logic such as this, I need to create all 5 different methods to support
      all the subclasses of the Number: Byte, Integer, Long, Float, Double.
      For IO logic within the JDK, you need the Byte, Integer pair as char is frequently converted into int.
      For SQL logic, you need the Long, Float, Double. Yes, you may ignore Float, but it has it place in J2ME?

      public static int isSame(Float val1, Float val2) {
      if (val1 == null || val2 == null) {
      return -1;
      }
      int nan = Float.floatToRawIntBits(Float.NaN);
      int raw1 = Float.floatToRawIntBits(val1.floatValue());
      int raw2 = Float.floatToRawIntBits(val2.floatValue());
      if (raw1 == nan) {
      return -1;
      }
      if (raw2 == nan) {
      return -1;
      }
      if (raw1 == raw2) {
      return 0;
      }
      // both not same
      return 1;
      }

      --------------------------------------------------
      These 2 signature prevented the creations of a simple single static Generic method for isSame(T val1, Tval2)
      Float.floatToRawIntBits(); /      Double.doubleToRawLongBits(double value)
      val1.floatValue(); / val1.doubleValue(); /...
      Because they are all different signature from Byte, Integer, Long, Double.

      Yes. The code can be changed to check for the datatype that extends from Number, but it seems to
      makes code even more complex.
      Extension of HashMap for numeric types

      Please note:
      public enum ArithmeticType{} is needed. Code is complex and harder to read.

      IF, there are new method signature that is such as this:
      Double.value(); / Float.value() / Integer.value()...
      Double.toRawBits(); / Float.toRawBits() / Integer.toRawBits()...

      THIS would make the coding of static generic methods more simple and readable:

      public static <T extends Number> int isSame(T val1, T val2){
      if (val1 == null || val2 == null) {
      return -1;
      }
      long nan = Number.toRawBits(Number.NaN); // Made possible because of NEW Signature at Parent Class.
      long raw1 = Number.toRawBits(val1.value()); // Made possible because of NEW Signature at Parent Class.
      long raw2 = Number.toRawBits(val2.value()); // Made possible because of NEW Signature at Parent Class.
      if (raw1 == nan) {
      return -1;
      }
      if (raw2 == nan) {
      return -1;
      }
      if (raw1 == raw2) {
      return 0;
      }
      // both not same
      return 1;
      }

      The above is single example of the situation. There might be other API in the JDK with the similar situation because of
      signature pattern that would have made coding a single static generic method not too easy

      Please see EVEN in the new JDK 1.7:
      http://download.oracle.com/javase/7/docs/api/java/lang/Number.html

      Perhaps There is also an existing way to do that without complicating the code tooo much? Please show with working sample code.
        • 1. Re: How To simplied Code Pattern in Generics?
          EJP
          public static int isSame(Float val1, Float val2) {
          You want to make that generic? with that name?

          It seems to me that ll you need to do is call the compareTo() method after a null check. The rest of it is pointless, and the compareTo() method being polymorphic you don't need Generics either.
          • 2. Re: How To simplied Code Pattern in Generics?
            866364
            Hi,

            The looks is very misleading. Try that out. See if that is possible.

            I use that to simplified example to avoid messing up the point of the question.

            The rule is simple, a single static generic method to handles all the basic data type within that newly defined method.

            It is an simple example of how to define static generic method that need to use.

            This only show a simple pattern static pattern.
            How about when you need to code some IO related classes methods that is similar to java.io.DataOutputStream?

            Do you understand what I am trying to asked here?

            Matthew Ong
            • 4. Re: How To simplied Code Pattern in Generics?
              866364
              The end point is to allow caller to isSame method to do this:

              // they are all primitive of a different type.
              byte num0=22;
              int num1=22;
              long num2=22L;
              float num3 = 22.0f;
              double num4=22.0;

              // Using the same static method to check all 4 different types of number.
              Numbers.isSame(num0, num4); // return true;
              Numbers.isSame(num1, num2); // return true;
              Numbers.isSame(num3, num4); // return true;
              Numbers.isSame(num4, num1); // return true;

              Do you understand how that single static method can be done currently?
              Is it impossible because they are all comparing different primitive type.
              • 5. Re: How To simplied Code Pattern in Generics?
                802316
                The problem you have with Number is that you have to consider all types.

                BigInteger, BigDecimal, AtomicInteger and AtomicLong are all Number.

                The BigInteger and BigDecimal don't fit into a long value.

                Also a long value, a double as raw bits and a float as raw bits cannot be compared.
                float f = Float.POSITIVE_INFINITY;
                long l = 2139095040L;
                double d = 1.0568533725E-314;
                
                long n1 = Float.floatToRawIntBits(f);
                long n2 = l;
                long n3 = Double.doubleToRawLongBits(d);
                System.out.println(n1 == n2); // true
                System.out.println(n2 == n3); // true
                Trying to use the raw bits, the method would return true for
                Number.isSame(Float.POSITIVE_INFINITY, 2139095040L)  // same raw bits.
                Number.isSame(Float.POSITIVE_INFINITY, 1.0568533725E-314)  // same raw bits
                I don't think it would be very useful.

                The closest you can come to comparing Numbers regardless of type is to use the following
                Number n1 =
                Number n2 =
                int cmp = new BigDecimal(n1.toString()).compareTo(new BigDecimal(n2.toString()));
                This doesn't work for null, Nan, infinity or -0.0. ;)
                • 6. Re: How To simplied Code Pattern in Generics?
                  866364
                  Hi Peter,

                  I am well aware of this issue. That is why I posted this thread.

                  Disregard the BigDecimal and also BigInteger class. Focus on the primitive values only.

                  I found out that many existing JDK API method pattern, cannot mix well with the new Generic Syntax.
                  It seems that it needs to make use of complicated if-else or looping logic to get things done across different
                  data type.

                  It is more of a signature pattern and NOT a Generic Syntax problem.

                  I wonder if there is a way to bring this up to JDK developer to fix this.

                  Yes. The code can be changed to check for the datatype that extends from Number, but it seems to
                  makes code even more complex.
                  Extension of HashMap for numeric types

                  Such method are missing to allow me to code a SINGLE static method withpit complex switching.

                  long nan = Number.toRawBits(Number.NaN); // Made possible because of NEW Signature at Parent Class.
                  long raw1 = Number.toRawBits(val1.value()); // Made possible because of NEW Signature at Parent Class.
                  long raw2 = Number.toRawBits(val2.value()); // Made possible because of NEW Signature at Parent Class.




                  Please note:
                  public enum ArithmeticType{} is needed. Code is complex and harder to read.

                  Edited by: matt_idea on Jun 3, 2011 10:42 PM

                  Edited by: matt_idea on Jun 3, 2011 10:53 PM
                  • 7. Re: How To simplied Code Pattern in Generics?
                    796440
                    This issue hardly seems worth the effort you've put into this thread. Fine, so the type system/method signature rules/generics/whatever don't handle this particular use case--a rather esoteric corner case, in my opinion. So you write your method with it's "complicated" if/else structure, unit test the snot out of it, stuff it in your commons library, and forget about it.

                    Sure it would be nice if you could write that method cleanly and simply, but not all problems can be solved that way. Sometimes you have no choice but to write ugly, complex code. But you comment it, test it, and give it a clean public interface, and then move on with your life.
                    • 8. Re: How To simplied Code Pattern in Generics?
                      866364
                      Please take note of this:

                      An issue is met on Generics and java.lang.Number subclasses. It *seems to be MORE of a API design
                      method pattern* that cannot 'join' nicely with Generics Syntax rather than a Generic Syntax Issue.

                      To explain the issue, a simple logic such as this, I need to create all 5 different methods to support
                      all the subclasses of the Number: Byte, Integer, Long, Float, Double.
                      For IO logic within the JDK, you need the Byte, Integer pair as char is frequently converted into int.
                      For SQL logic, you need the Long, Float, Double. Yes, you may ignore Float, but it has it place in J2ME?

                      It is NOT just about Numbers.isSame() ONLY. Other places where primitive type that can be handled similarly
                      when you write your own classes and library.

                      Adding some useful common signature will help a lot. I will show a more complex useful example.
                      This code is still simplified on purposed to show that issue.
                      -----------------------------------------------------------------------------------------------------------------------------------------------------------

                      public class NamedBag<T> {

                      HashMap<String, T> mKeyValHash = null;

                      public T getValue(String key, T defaultVal) {
                      if (mKeyValHash == null) {
                      return defaultVal;
                      }
                      T val = mKeyValHash.get(key);
                      if (val == null) {
                      return defaultVal;
                      }
                      if (val instanceof String) {
                      if (StringTools.empty((String) val)) {
                      return defaultVal;
                      }
                      }
                      // Block A
                      if (val instanceof Double) {
                      double value = ((Double) val).doubleValue();
                      if (Double.isNaN(value)) {
                      return defaultVal;
                      }
                      }
                      // Block B
                      if (val instanceof Float) {
                      float value = ((Float) val).floatValue();
                      if (Float.isNaN(value)) {
                      return defaultVal;
                      }
                      }
                      return val;
                      }

                      }
                      ------------------------------------------------------------------------------------------------------------------------------------------------------------------

                      Block A & B and other numeric base code can also share the same block IF they have some COMMON Signature.

                      There is going to be other similar situation when another library is needed for: IO, SQL, PDF, XML, SWING ...

                      Do you see a repeating coding pattern problem here?

                      I suspect there are other type of API within JDK is NOT updated to allow reusable mix with the new/old Generics.
                      • 9. Re: How To simplied Code Pattern in Generics?
                        796440
                        matt_idea wrote:
                        Please take note of this:
                        Sorry, but I'm not really interested enough in the problem to pay it that much attention. If I have misunderstood, then simply ignore my comments.

                        The problem I think you're having, I've run across a few times myself, spent a little time looking for a clean solution, didn't find one, shrugged my shoulders, said, "Oh, well," wrote an ugly solution with a clean interface, and moved on.

                        If you're having some serious problem that comes up in day-to-day coding, for many different situations, rather than an occasional one-off, then this is something that I have never encountered in 12+ years of Java development, and I'm really not interested in trying to figure out what this situation is where it's such a major problem for you.

                        Good luck though.

                        EDIT: I will add, however, that if this is truly a serious hurdle in your problem domain, then perhaps the Java language is not an appropriate tool for you. If you want to run on the Java platform, however, maybe another language, such as Scala or Groovy, would suit you better. Both of these languages have the advantage that you can write your code completely in Java syntax (or very nearly so) and it will behave as you would expect Java code to behave, but they have additional language features and flexibility not present in Java. Scala in particular is geared toward developing Domain-Specific Languages. There are of course other languages as well that run on the JVM. Find the right tool for your job.

                        Edited by: jverd on Jun 3, 2011 8:56 AM
                        • 10. Re: How To simplied Code Pattern in Generics?
                          866364
                          Hi jverd,

                          I am in the middle of defining something like a common library for Java but subset of JDK so that I can use the same library signature to
                          port over to another language like:

                          1) D Programming
                          2) Google Go
                          3) C#

                          Haxe done for PHP and others,
                          @see:
                          http://haxe.org/doc/intro

                          No, I am not involved with haXe, considering.

                          Hence, it would be best that extra scripting language is totally avoided entirely.
                          • 11. Re: How To simplied Code Pattern in Generics?
                            EJP
                            I still don't understand why you can't use compareTo(). Unless all the isSame() and toRawIntBits() usages have no bearing on the problem, in which case isSame() would be better with a more 'generic' name and toRawIntBits() should be left out of the problem statement altogether. As stated, surely the problem just reduces to:
                            public <T> boolean isSame(Comparable<T> c1, Comparable<T> c2)
                            {
                              return c1 == null ? c2 == null : c1.compareTo(c2) == 0;
                            }
                            • 12. Re: How To simplied Code Pattern in Generics?
                              866364
                              Thanks for the isSame sample code. Could that support primitive value and Not just wrapper class also?
                              Anyway, I will give it a try. Does those compare to uses raw bits to do checking?

                              It is NOT just about Numbers.isSame() ONLY. Other places where primitive type that can be handled similarly
                              when you write your own classes and library.

                              How about the NamedBag Class? How to do a simple method without all those complex type checking and switches and still be
                              correctly handling primitive type values? Yes. There is auto-boxing.

                              It seems to me as a work around rather than really supporting Generic along side with primitive types.


                              Please see this.
                              http://code.google.com/p/multi-language-bench/
                              and also
                              http://jeremymanson.blogspot.com/2011/06/scala-java-shootout.html

                              People that has determined that Java will:
                              3. ...The benchmark did not use Java collections effectively. It was generating millions of unnecessary objects per second, and the runtime was swamped by GC overhead. I

                              That shows that the default API is not Yet optimized to use the Generic Syntax and also auto-box.

                              I am trying to show a current mis-matched in Java Generic Syntax and API signature not able to support easily.
                              • 13. Re: How To simplied Code Pattern in Generics?
                                866364
                                Hi,

                                Here is the test code using your example.
                                -----------------------------------------------------------------------------------------------------------------------------------------
                                public class GenericTest {

                                public <T> boolean isSame(Comparable<T> c1, Comparable<T> c2) {
                                return c1 == null ? c2 == null : c1.compareTo(c2) == 0;
                                }

                                public static void main(String[] args) {
                                // they are all primitive of a different type.
                                byte num0 = 22;
                                int num1 = 22;
                                long num2 = 22L;
                                float num3 = 22.0f;
                                double num4 = 22.0;

                                // Using the same static method to check all 4 different types of number.
                                isSame(num0, num4); // return true; ### ERROR ###
                                isSame(num1, num2); // return true; ### ERROR ###
                                isSame(num3, num4); // return true; ### ERROR ###
                                isSame(num4, num1); // return true; ### ERROR ###
                                }
                                }
                                ----------------------------------------------------------------------------------------------------------------
                                I have error
                                D:\PersonalProject\TestJava\src\GenericTest.java:13: compareTo(T) in java.lang.Comparable<T> cannot be applied to (java.lang.Comparable<T>)
                                return c1 == null ? c2 == null : c1.compareTo(c2) == 0;
                                D:\PersonalProject\TestJava\src\GenericTest.java:25: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (byte,double)
                                isSame(num0, num4); // return true;
                                D:\PersonalProject\TestJava\src\GenericTest.java:26: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (int,long)
                                isSame(num1, num2); // return true;
                                D:\PersonalProject\TestJava\src\GenericTest.java:27: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (float,double)
                                isSame(num3, num4); // return true;
                                D:\PersonalProject\TestJava\src\GenericTest.java:28: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (double,int)
                                isSame(num4, num1); // return true;
                                5 errors
                                ------------------------------------------------------------------------------------------------------------------------------------------
                                Hopefully this show clearly the issue I am seeing. Others might have missed it.
                                • 14. Re: How To simplied Code Pattern in Generics?
                                  852060
                                  matt_idea wrote:
                                  It is NOT just about Numbers.isSame() ONLY. Other places where primitive type that can be handled similarly
                                  when you write your own classes and library.
                                  How many such operations can you name? I would be surprised to see you hit the double digits. Implement them once and be done with it.
                                  How about the NamedBag Class? How to do a simple method without all those complex type checking and switches and still be
                                  correctly handling primitive type values? Yes. There is auto-boxing.

                                  It seems to me as a work around rather than really supporting Generic along side with primitive types.
                                  Auto-boxing into primitive wrappers is probably more powerful than primitives in generics would be. Primitive wrappers are reference types; you can put bounds on type parameters for reference types and use those. I can't imagine a sensible specification for primitive upper bounds. And since the members of a type variable are those of the upper bound, the set of operations one could perform on primitves is empty. At best there would be specialization for primitve wrappers which could then work with unboxed objects in certain situations.
                                  Please see this.
                                  http://code.google.com/p/multi-language-bench/
                                  and also
                                  http://jeremymanson.blogspot.com/2011/06/scala-java-shootout.html

                                  People that has determined that Java will:
                                  3. ...The benchmark did not use Java collections effectively. It was generating millions of unnecessary objects per second, and the runtime was swamped by GC overhead. I

                                  That shows that the default API is not Yet optimized to use the Generic Syntax and also auto-box.
                                  No it does not. All it shows is that developers unfamiliar with a class library are likely to use inefficient implementations.
                                  I am trying to show a current mis-matched in Java Generic Syntax and API signature not able to support easily.
                                  So far you've not made much headway.
                                  matt_idea wrote:
                                  Hi,

                                  Here is the test code using your example.
                                  -----------------------------------------------------------------------------------------------------------------------------------------
                                  public class GenericTest {

                                  public <T> boolean isSame(Comparable<T> c1, Comparable<T> c2) {
                                  return c1 == null ? c2 == null : c1.compareTo(c2) == 0;
                                  }

                                  public static void main(String[] args) {
                                  // they are all primitive of a different type.
                                  byte num0 = 22;
                                  int num1 = 22;
                                  long num2 = 22L;
                                  float num3 = 22.0f;
                                  double num4 = 22.0;

                                  // Using the same static method to check all 4 different types of number.
                                  isSame(num0, num4); // return true; ### ERROR ###
                                  isSame(num1, num2); // return true; ### ERROR ###
                                  isSame(num3, num4); // return true; ### ERROR ###
                                  isSame(num4, num1); // return true; ### ERROR ###
                                  }
                                  }
                                  ----------------------------------------------------------------------------------------------------------------
                                  I have error
                                  D:\PersonalProject\TestJava\src\GenericTest.java:13: compareTo(T) in java.lang.Comparable<T> cannot be applied to (java.lang.Comparable<T>)
                                  return c1 == null ? c2 == null : c1.compareTo(c2) == 0;
                                  D:\PersonalProject\TestJava\src\GenericTest.java:25: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (byte,double)
                                  isSame(num0, num4); // return true;
                                  D:\PersonalProject\TestJava\src\GenericTest.java:26: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (int,long)
                                  isSame(num1, num2); // return true;
                                  D:\PersonalProject\TestJava\src\GenericTest.java:27: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (float,double)
                                  isSame(num3, num4); // return true;
                                  D:\PersonalProject\TestJava\src\GenericTest.java:28: <T>isSame(java.lang.Comparable<T>,java.lang.Comparable<T>) in GenericTest cannot be applied to (double,int)
                                  isSame(num4, num1); // return true;
                                  5 errors
                                  ------------------------------------------------------------------------------------------------------------------------------------------
                                  Hopefully this show clearly the issue I am seeing. Others might have missed it.
                                  Just implement two methods:

                                  isSameD(double, double)
                                  isSameL(long, long)

                                  Any case involving exclusively integral types is handled by isSameL, all the others by isSameD. The combination of a long and a float or double entails loss of precision; feel free to add two more methods to handle those.

                                  With kind regards
                                  Ben
                                  1 2 Previous Next