Okay, here's a simple example that should clear this all up: Case scenario: I have a method that accepts a list of Strings, using each string in the list to fill a table row. Our model actually supports 'sparse' rows, so, nulls in the input list indicate that that particular column doesn't contain anything. Most users don't use the sparse row facility, but a few do. This is our method in vanilla java land:
public void setRowValues(List<String>) { //do stuff } so far, so good. Now we want to add nullity to this. In our case. We clearly allow nulls, so we write: public void setRowValues(List!<String?> values) { //to clarify: A non-null list which contains only Strings or 'null'. } Great, so, now, I'm the caller, and I have a list of strings ready to pass to this method. For whatever reason, my list of strings is of the List<String!> variety; Let's say I'm not using the sparse row facility and my code isn't capable of handling them, so its actually great that I can use List!<String!> to get compile time checking that I don't acidentally go there. so I write: List!<String!> myValues = Arrays.asList("foo", "bar", "baz"); //for arguments sake, lets say Arrays.asList returns List!<String!> here. row.setRowValues(myValues); ... and I get a compiler error when I compile it: List<String!> is not assignment compatible to a List<String?>. (If it would have been, then, what happens when our setRowValues adds a value to the list? It can clearly do: "values.add(null);" ) This bewilders me to no end. I give up, and curse at the author of this library. That's clearly not an acceptable scenario. So far you haven't shown me anything about avoiding that scenario. NB: You can sneakily fix it here by using <? extends String>, even though that looks like a stupid bound, and will trigger IDE warnings, as 'String' is final. However, imagine that we actually do add things to this list, but we don't add 'null', regardless of input. Then this silly trick no longer works. On Oct 23, 9:12 am, "Viktor Klang" <[EMAIL PROTECTED]> wrote: > On Thu, Oct 23, 2008 at 5:15 AM, Reinier Zwitserloot <[EMAIL PROTECTED]>wrote: > > > > > > > Inline... > > > On Oct 21, 1:55 pm, "Viktor Klang" <[EMAIL PROTECTED]> wrote: > > > > If many of the ugly if-checks are eliminated, and many NPEs are avoided, > > I > > > would be rather surprised if LoC wouldn't drop drastically (even though > > the > > > "problem" mentioned above) > > > That's the goal, yes, but, look at the backwash against generics. It > > has to be pretty perfect. > > > > List!<?! super Foo>.get(0) would yield either an OOBE or Foo! (and Foo! > > can > > > be autocasted to Foo?) > > > No, that makes no sense. <? extends Foo> would yield Foo or Foo! ; ? > > super Foo 'yields' Object. > > Sorry, was retarded when I wrote that. > > <?! super Foo> means something that is a supertype of Foo and never null. > > > > > You can *ADD* "Foo" to it. Assuming you meanet that List<?! super > > Foo>.get(0) yields an OOBE or Object!, then... > > > we have a problem. If we do that, then <?! super Foo> is not capable > > of holding a <?? super Foo>. Contrast this to extends, where we've > > proven that: > > > <?? extends Foo> is capable of holding a <?! extends Foo> without any > > issues. > > > We can solve the problem by letting the rarely used get()-style > > operation (return type of T) in combination with <?! super Foo> return > > T? and not T!, but that makes very little sense; why would ?! return > > non-! - that's kind of weird. > > This makes no sense, Why should it return T? (T? = T or null) > > > > > > > > > Now try this with no bounds, just a type, e.g "List<String>". Without > > > > all three modifiers (non-null, definitely null, unknown), you just > > > > can't cover all reasonable use cases. > > > > List<String> is syntactic sugar for List?<String?> :) > > > No - try writing a non-particular generics bound (non-particular in > > the sense of nullness). You've got 3 options here, and they are all > > vastly different and incompatible: > > > String! - can not be null (advantage: you can read out without null- > > checks). > > String? - can be null (advantage: you can write nulls into this thing) > > String- - can be either, you don't know (advantage: You can accept > > either String! or String?). > > But that was what I told you, if you do not care about nullness, then you > use <type>? since <type>! can be promoted to <type>? > > > > > > > Again, not having that third option sounds to me like a recipe for > > utter disaster. It's not only generally annoying, but in light of the > > fact that legacy code will lead to lots of situations where types have > > the wrong type of nullity, it seems extremely important to be able to > > write flexible methods that accept either. > > > > So, if we boil it down, what are the benefits and drawbacks? > > > It's good - no doubt about it. Just like generics was good - no doubt > > about it. The drawback is, that it's just as complicated as generics, > > with just as much funky syntax. The one advantage, due to limited > > types (specifically, only three types: non-null, allows-null, unknown- > > null), is that I foresee far fewer 'puzzlers'. > > For me, there are still only 2 different types ;) > > > > -- > Viktor Klang > Senior Systems Analyst --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to javaposse@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/javaposse?hl=en -~----------~----~----~----~------~----~------~--~---