Is a MyClass[] also an Object[]?

Discussion in 'Java' started by Andrea Desole, Jan 28, 2005.

  1. This is something someone just told me after discussing the
    implementation of methods working with arrays.
    Now, I have a few questions:
    is it true?
    If it's true, can I also say that Derived[] is also a Base[]?
    Any reference available?
    Thanks

    Andrea
    Andrea Desole, Jan 28, 2005
    #1
    1. Advertising

  2. Andrea Desole <_SPAM_PLEASE.nl> writes:

    > is it true?


    No. Both MyClass[] and Object[] are objects of their own "class" which
    directly extends java.lang.Object. They are not related.
    Tor Iver Wilhelmsen, Jan 28, 2005
    #2
    1. Advertising

  3. Andrea Desole

    Bob Guest

    Andrea Desole wrote:
    > This is something someone just told me after discussing the
    > implementation of methods working with arrays.
    > Now, I have a few questions:
    > is it true?
    > If it's true, can I also say that Derived[] is also a Base[]?



    If you mean: can you assign an array of type Derived to an array
    reference variable declared as type Base, then yes you can.

    class Base {}
    class Derived extends Base {}

    Base[] baseArray;
    Derived[] derivedArray = new Derived[x];
    baseArray = derivedArray;

    (Despite what I said a few posts ago, when confused.)

    Also, given the above, both the following expressions are true:

    (derivedArray instanceof Object)
    (baseArray instanceof Object)

    as arrays are always objects.
    --
    Bob
    Bob, Jan 28, 2005
    #3
  4. Bob wrote:
    > Andrea Desole wrote:
    >
    >> If it's true, can I also say that Derived[] is also a Base[]?

    >
    >
    >
    > If you mean: can you assign an array of type Derived to an array
    > reference variable declared as type Base, then yes you can.
    >
    > class Base {}
    > class Derived extends Base {}
    >
    > Base[] baseArray;
    > Derived[] derivedArray = new Derived[x];
    > baseArray = derivedArray;
    >
    > (Despite what I said a few posts ago, when confused.)


    so if I have the following methods:

    void foo( Base[] bases )
    void bar( Object[] objects )

    I can call:

    foo( derivedArray )
    bar( derivedArray )
    bar( baseArray )

    Is there a place where I can find it? Is it in the language
    specification somewhere?
    Andrea Desole, Jan 28, 2005
    #4
  5. Andrea Desole

    Bob Guest

    Andrea Desole wrote:

    > so if I have the following methods:
    >
    > void foo( Base[] bases )
    > void bar( Object[] objects )
    >
    > I can call:
    >
    > foo( derivedArray )
    > bar( derivedArray )
    > bar( baseArray )



    Yes. But to be certain I'm not giving you false information (and because
    I've got too much time on my hands), I wrote and compiled the following
    code:

    /* BEGIN CODE EXAMPLE */
    class Base {}

    class Derived extends Base {}

    public class TestArrayPolymorphism {
    public static void main(String [] args) {
    Base [] baseArray = new Base[4];
    Derived [] derivedArray = new Derived[4];

    foo(derivedArray);
    bar(derivedArray);
    bar(baseArray);

    System.out.println("Finished.");
    }

    public static void foo(Base [] bArray) {
    System.out.println("foo called with argument " + bArray);
    }

    public static void bar(Object [] oArray) {
    System.out.println("bar called with argument " + oArray);
    }
    }
    /* END CODE EXAMPLE */


    The code compiled without error, and running it gives the following output.

    foo called with argument [LDerived;@1add2dd
    bar called with argument [LDerived;@1add2dd
    bar called with argument [LBase;@eee36c
    Finished.


    However, (and this is what I was thinking of a few posts ago when I was
    confused) you CANNOT assume the same is true for primitive arrays. For
    example, you cannot assign a byte array to a reference variable declared
    to be an int[] array, even though you are permitted to store a byte
    value in an int variable. (You can still store a byte into an *element*
    of an int array, e.g. intArray[0] = byteValue.)

    > Is there a place where I can find it? Is it in the language
    > specification somewhere?


    To be honest, I'm not sure. I only know because I taught myself with a
    book that trains you for the SCJP exam.

    Let me see... a quick search turned up the Java Language Specification

    http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html#27805

    The Sun Java Tutorials don't seem to mention this in their array
    section, so the Java Language Specification is probably your best resource.
    --
    Bob
    Bob, Jan 28, 2005
    #5
  6. Tor Iver Wilhelmsen wrote:

    > Andrea Desole <_SPAM_PLEASE.nl> writes:
    >
    >
    >>is it true?

    >
    >
    > No. Both MyClass[] and Object[] are objects of their own "class" which
    > directly extends java.lang.Object. They are not related.


    That is technically correct, but not at all the whole story. Java
    specifies that there is a "widening reference conversion" "From any
    array type SC[] to any array type TC[], provided that SC and TC are
    reference types and there is a widening conversion from SC to TC." (JLS
    2e, 5.1.4). Widening reference conversions are among those that are
    allowed in assignments, method invocations, and casts, and hence are
    also accounted for by the instanceof operator and the methods of class
    Class that examine assignment compatibility. Therefore, although the
    class corresponding to MyClass[] is not a subclass of that corresponding
    to Object[], Java behaves in almost every way as if it were. In
    particular, the following is completely legal Java (barring any simple
    typos):

    class MyClass {}

    public class Main {
    void method(Object[] oa) {}

    public static void main(String[] args) {
    MyClass[] myArray = new MyClass[0];

    // assign a MyClass[] reference to a variable of type Object[]:
    Object[] objArray = myArray;

    /*
    * pass a MyClass[] reference to a method argument of type
    * Object[]
    */
    method(myArray);

    /*
    * A MyClass[] reference passes an "instanceof Object[]" test
    */
    if (myArray instanceof Object[]) {
    // Will be printed:
    System.out.println("All your base are belong to us");
    }
    }
    }


    John Bollinger
    John C. Bollinger, Jan 28, 2005
    #6
  7. Andrea Desole

    Chris Smith Guest

    Tor Iver Wilhelmsen <> wrote:
    > Andrea Desole <_SPAM_PLEASE.nl> writes:
    >
    > > is it true?

    >
    > No. Both MyClass[] and Object[] are objects of their own "class" which
    > directly extends java.lang.Object. They are not related.


    I think you'll find that, as kludgy as it is, MyClass[] does indeed
    extend Object[]. See the API docs for java.lang.ArrayStoreException as
    well.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 28, 2005
    #7
  8. Bob wrote:
    >
    > Let me see... a quick search turned up the Java Language Specification
    >
    > http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html#27805


    thank you, this was interesting. I specially found interesting par.
    10.10, which makes me think such an easy conversion between Base[] and
    Derived[] shouldn't maybe be allowed, because it implies a possible
    inconsistent behaviour
    Andrea Desole, Jan 28, 2005
    #8
  9. Andrea Desole

    Chris Uppal Guest

    Andrea Desole wrote:

    > I specially found interesting par.
    > 10.10, which makes me think such an easy conversion between Base[] and
    > Derived[] shouldn't maybe be allowed, because it implies a possible
    > inconsistent behaviour


    The main problems with the way that a Derived[] is allowed to be used where a
    Base[] is expected are that:

    a) Using
    aBaseArray[3] = aBaseInstance;
    will require a runtime check, unless the runtime JITer can prove to itself that
    the object referred to by "aBaseArray" is not in fact an instance of Dervied[]
    (or, I suppose, if it could prove that "aBaseInstance" is not in fact a
    Derived. I've never seen any claims that any JVM implementation actually does
    that kind of proof, and you would normally assume that all array /writes/
    require a type check (as well as a bounds check).

    b) The write to an array can in fact fail at runtime -- i.e. its a hole in the
    type system.

    c) The notion of assignability (and the isAssignableFrom() methods) don't
    follow the actual class hierarchy as closely as you'd expect.

    -- chris
    Chris Uppal, Jan 28, 2005
    #9
  10. Chris Uppal wrote:

    > c) The notion of assignability (and the isAssignableFrom() methods) don't
    > follow the actual class hierarchy as closely as you'd expect.


    I think this is what I mean. If I have a method that takes a Base[] I
    would expect, in that method, the possibility to replace an element in
    that array. And this is indeed possible if I give to my method a Base[].
    But if I give a Derived[] this is not possible anymore. This is quite
    inconsistent.
    Andrea Desole, Jan 28, 2005
    #10
  11. Andrea Desole

    Bob Guest

    Andrea Desole wrote:
    > Bob wrote:
    >
    >> Let me see... a quick search turned up the Java Language Specification
    >>
    >> http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html#27805

    >
    > thank you, this was interesting. I specially found interesting par.
    > 10.10, which makes me think such an easy conversion between Base[] and
    > Derived[] shouldn't maybe be allowed, because it implies a possible
    > inconsistent behaviour


    That is an interesting point, and something I wasn't aware of. And I
    agree that it could cause problems. Any method that takes an object
    array and updates its contents could fall foul of this incompatibility,
    unless the reference type was marked as final.
    --
    Bob
    Bob, Jan 28, 2005
    #11
  12. Chris Smith wrote:

    > I think you'll find that, as kludgy as it is, MyClass[] does indeed
    > extend Object[]. See the API docs for java.lang.ArrayStoreException as
    > well.


    Nope. From JLS 2e, section 10.8: "The direct superclass of an array
    type is Object." See my response to Tor, however.


    John Bollinger
    John C. Bollinger, Jan 28, 2005
    #12
  13. Andrea Desole wrote:

    > Chris Uppal wrote:
    >
    >> c) The notion of assignability (and the isAssignableFrom() methods)
    >> don't
    >> follow the actual class hierarchy as closely as you'd expect.

    >
    >
    > I think this is what I mean. If I have a method that takes a Base[] I
    > would expect, in that method, the possibility to replace an element in
    > that array. And this is indeed possible if I give to my method a Base[].
    > But if I give a Derived[] this is not possible anymore. This is quite
    > inconsistent.


    Your argument is sound. I think this is an area where the Java
    designers compromised OO principles to provide for easier use, but the
    cost is as you describe. All in all, I think I'll accept this
    particular compromise -- I have certainly made use of the language
    feature to my advantage, but I have rarely seen an ArrayStoreException.
    Knowing about this is half the battle, and carefully documenting
    method behavior is the other half.


    John Bollinger
    John C. Bollinger, Jan 28, 2005
    #13
  14. Andrea Desole

    Chris Smith Guest

    John C. Bollinger <> wrote:
    > Chris Smith wrote:
    >
    > > I think you'll find that, as kludgy as it is, MyClass[] does indeed
    > > extend Object[]. See the API docs for java.lang.ArrayStoreException as
    > > well.

    >
    > Nope. From JLS 2e, section 10.8: "The direct superclass of an array
    > type is Object." See my response to Tor, however.


    Hmm. Learn something new every day.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 28, 2005
    #14
  15. Andrea Desole

    Chris Smith Guest

    Bob <-sig.con> wrote:
    > That is an interesting point, and something I wasn't aware of. And I
    > agree that it could cause problems. Any method that takes an object
    > array and updates its contents could fall foul of this incompatibility,
    > unless the reference type was marked as final.


    It's interesting to contrast this to the generics spec in Java 1.5.
    Arrays are, after all, merely a special case of the general idea of
    generic types.

    In generics, List<MyClass> is *not* related to List<Object> in any way.
    However, there are extensions to data types that define new rules for
    their compatibility with certain values... for example, there is the
    type List<? super MyClass>, which is a reference type that can point to
    objects of class List<MyClass> or List<Object>. There is also
    List<? extends MyClass>, which can point to objects of List<MyClass> and
    List<DerivedClass>, where DerivedClass extends MyClass. Certain
    operations of List (for example, add) can't be performed with a
    List<? extends MyClass> reference, and other operations (for example,
    get) are restricted to work with the Object class when called on a
    List<? super MyClass> reference.

    The trade-off is clear. The case with generics above is somewhat
    complex; perhaps too complex for a large base of people adjusting to
    Java before it was an established language. On the other hand, arrays
    create a fault in type safety. The choice of which is desirable is, in
    the end, up for grabs. We do know which way Sun is moving, though.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Jan 28, 2005
    #15
  16. Andrea Desole

    Bob Guest

    John C. Bollinger wrote:
    >
    > Your argument is sound. I think this is an area where the Java
    > designers compromised OO principles to provide for easier use, but the
    > cost is as you describe. All in all, I think I'll accept this
    > particular compromise -- I have certainly made use of the language
    > feature to my advantage, but I have rarely seen an ArrayStoreException.
    > Knowing about this is half the battle, and carefully documenting method
    > behavior is the other half.


    I would think that one answer would be to create a method in the
    following way, to be safe:

    Base[] methodName(Base[] argArray) {
    Base [] newArray = new Base[argArray.length];

    for (int i = 0; i < argArray.length; ++i) {
    newArray = argArray;
    }

    // Perform operations on newArray

    return newArray;
    }


    Perhaps not the most efficient way of doing things, but at least you
    would avoid trying to illegally modify any arrays that were a subclass type.
    --
    Bob
    Bob, Jan 28, 2005
    #16
  17. Andrea Desole

    Chris Uppal Guest

    John C. Bollinger wrote:

    > I think this is an area where the Java
    > designers compromised OO principles to provide for easier use, but the
    > cost is as you describe. All in all, I think I'll accept this
    > particular compromise -- I have certainly made use of the language
    > feature to my advantage, but I have rarely seen an ArrayStoreException.


    I've /never/ seen one (caused by this issue), not ever.

    So I think the Java designers were right to ditch static type soundness (which
    is /not/ part of "OO principles", IMO) to allow greater flexibility. There's
    no doubt that its an ugly wart in the system, but I don't think it does much
    harm in reality, and there's no way to "fix" the type system without
    introducing a great deal of unwanted complexity (can you spell "generics" ? ;-)

    -- chris
    Chris Uppal, Jan 29, 2005
    #17
  18. "John C. Bollinger" <> wrote in message
    news:cte8dp$5ss$...

    > Your argument is sound. I think this is an area where the Java designers
    > compromised OO principles to provide for easier use, but the cost is as
    > you describe. All in all, I think I'll accept this particular
    > compromise -- I have certainly made use of the language feature to my
    > advantage, but I have rarely seen an ArrayStoreException.



    Nor have I. Without this feature, it would have been impossible to write
    many of the useful methods in the Arrays class that take generic Object[]
    parameters until 1.5.
    Mike Schilling, Jan 30, 2005
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mario Fratelli
    Replies:
    32
    Views:
    1,355
    Phlip
    Dec 9, 2003
  2. Dave
    Replies:
    1
    Views:
    343
    Ron Natalie
    Dec 8, 2003
  3. modemer
    Replies:
    11
    Views:
    625
    modemer
    Mar 21, 2005
  4. Gunnar G
    Replies:
    5
    Views:
    364
    Howard
    Jul 8, 2005
  5. Replies:
    4
    Views:
    327
Loading...

Share This Page