looping through a list, starting at 1

A

Andreas Leitgeb

Arved Sandstrom said:
Pretty much in the standard way, which would take advantage of the
marker interface in a way suggested by Bloch: you create an interface
that extends List and RandomAccess, and concrete classes implement that.

That's just not applicable to the Collections framework as it is:
We've all been taught to use interface-names for the static type
of variables to hold whatever concrete implementation:
ArrayList l = new ArrayList(); // discouraged
List l = new ArrayList(); // encouraged

As soon as I use a statically "List"-typed variable to hold my
ArrayList instance, I've irrevocably disposed of the *static*
information about RandomAccess'ness of the instance.

If we were to change the Collection framework to allow for static
dealing with RandomAccess'ness, then we would first need that new
interface RandomAccessList extends List,RandomAccess {}
and would then need all appropriate implementations to implement
that new interface. And also we would need to statically type
certain variables as RandomAccessList, if we really wanted the
compiler to be able to statically decide among a RandomAccess-
optimized code path or the default one (without locking in on
particular implementations).

That's of course just rambling. Marker-interfaces just aren't used that
way, but instead they are always checked at runtime. So, either Marker-
interfaces (such as RandomAccess) are an anti-pattern themselves, or
that pattern is one declared exception to the "instanceof"-red flag.
 
S

supercalifragilisticexpialadiamaticonormalizeringe

I specifically answered your question "Are marker-interfaces (which
RandomAccess is, iirc) already an antipattern". IMO they are not, for
reasons stated. But this non-anti-pattern explanation emphasizes their
use as compile-time new types. Their not inconsiderable utility here
stems from the fact that the marker interface guarantees a behaviour in
a documented contract - it's up to the implementor to meet those guarantees.

It's up to the implementor to meet guarantees with any interface, even
one that declares methods. The compiler can enforce the presence of
methods with particular signatures, but that's as far as it goes. It's
as easy to write a delegate EvilList extends LinkedList implements
RandomAccess and to write something like:

public class EvilIterator implements Iterator<String> {
public boolean hasNext () {
return true;
}
public String next () {
throw new NoSuchElementException();
}
public void remove () {
throw new IllegalArgumentException();
}
}
 
L

Lew

That's just not applicable to the Collections framework as it is:
We've all been taught to use interface-names for the static type
of variables to hold whatever concrete implementation:
ArrayList l = new ArrayList(); // discouraged
List l = new ArrayList(); // encouraged

No, that's not what we've been taught. We've been taught to use the type that most generally allows the compiler to enforce the specific contract we need. That does not always mean use the interface (not "names"), nor the most general interface. Sometimes you do want to peg a variable or return type to a specific implementation, or a specific interface, or an interface that mixes in two parent interfaces per Bloch. Don't make a religion of "use the (most general) interface" - the actual principle is "use the type that guarantees your contract". So 'RandomList extends List, RandomAccess' is perfectly acceptable.
....
That's of course just rambling. Marker-interfaces just aren't used that
way, but instead they are always checked at runtime. So, either Marker-

Nope. Their value is when they're checked *at compile time*.

It's the use at run time that is suspect.
interfaces (such as RandomAccess) are an anti-pattern themselves, or
that pattern is one declared exception to the "instanceof"-red flag.

Marker interfaces are not an antipattern. Use of 'instanceof' is, often.

Use marker interfaces for *compile time* safety.
 
A

Andreas Leitgeb

Lew said:
Andreas said:
Lew said:
Volker Borchert wrote:
if (l instanceof RandomAccess) {
Tests on type like this are an antipattern.
Are marker-interfaces (which RandomAccess is, iirc) already an
antipattern, or is there a different way to check for them, [...]
With generics you can use type intersections so that something has to be
both 'List' and 'RandomAccess' (again, say) even to reach the call or the
class or whatever.

Interesting stuff! (but still falls a bit short):

--- snip SSCCE Test.java ---
import java.util.*;
public class Test {
public static void main(String[] args) {
method( new ArrayList(42) );
method( new Vector(42) );
//method( new LinkedList(42) ); // would error: good!
}

public static <T extends List,RandomAccess> T method(T raAcList) {
return raAcList;
}

//Provide a fallback overload for all Lists: doesn't compile
// public static <T extends List> T method(T anyList) {
// return anyList;
// }

//Nor does this compile together with the generic one:
// public static List method(List anyList) {
// return anyList;
// }
//with Object for the param-type it would compile, but not
//help to filter for Lists at compile-time.
}
--- snip ---

So, while I could write a method that takes only objects which are
both List and RandomAccess, I cannot provide a less-picky overload,
that would only filter on List.
(This appears like a shortcoming to me, which may eventually be
fixed, but it doesn't work with 1.6.0_26.)
It's the run-time type check that one often wishes to avoid.
Of course, if the logic truly requires it, as it sometimes does,
then the antipatternness goes away. I just find that use of
'instanceof' in the world of types and generics frequently
signals incompletely thought-out type assertions.

Well, for now, I guess we'll just have to face that it is necessary
more often than it would be in an ideal Java.
If there were an SSCCE for the particular use case, one might
be able to discern a less run-timeish way forward or one might not.

The case at hand didn't really suffer from the distinction.
The object is asked at runtime if it is a RandomAccess, and
either way correct (hope so) and appropriate code is executed
for the object. It's not principially different from asking
a (list-)object if it is empty(), and do something appropriate
in each case.
I only wished to point out a general principle here.

Thanks for pointing out the trick with generics, even though
it doesn't yet fully work. I hadn't thought of that, and might
run into a situation where it could prove useful.
 
A

Andreas Leitgeb

Lew said:
No, that's not what we've been taught.
We've been taught to use the type that most generally allows the compiler
to enforce the specific contract we need.

Fair enough. If I was to write code that was supposed to work for both
types (with or without a particular marker interface), then in the part
for "no marker" (as statically determined) I'd better still add a runtime-
check for it. In theory, theory and practise are the same, in practise
they aren't. :)
Marker interfaces are not an antipattern. Use of 'instanceof' is, often.
Use marker interfaces for *compile time* safety.

I wonder, if that is done in practise. E.g.: do you happen to know code
in the Java Standard Library or other renowned project that does this kind
of static check for a marker-interface?
 
L

Lew

Andreas said:
Lew said:
Andreas said:
Lew wrote:
Volker Borchert wrote:
if (l instanceof RandomAccess) {
Tests on type like this are an antipattern.
Are marker-interfaces (which RandomAccess is, iirc) already an
antipattern, or is there a different way to check for them, [...]
With generics you can use type intersections so that something has to be
both 'List' and 'RandomAccess' (again, say) even to reach the call or the
class or whatever.

Interesting stuff! (but still falls a bit short):

--- snip SSCCE Test.java ---
import java.util.*;
public class Test {
public static void main(String[] args) {
method( new ArrayList(42) );
method( new Vector(42) );
//method( new LinkedList(42) ); // would error: good!
}

public static <T extends List,RandomAccess> T method(T raAcList) {
return raAcList;
}

//Provide a fallback overload for all Lists: doesn't compile
// public static <T extends List> T method(T anyList) {
// return anyList;
// }

You cannot have two erasure-equivalent methods in the same class, so that'swhy both won't co-exist.

The generics trick is suitable when you want to insist that the argument beof the particular type, not when you want to bifurcate as you indicated. It seems as though perhaps you are in a situation where you want to fork onthe type at run-time, but I am not convinced yet.
The object is asked at runtime if it is a RandomAccess, and
either way correct (hope so) and appropriate code is executed
for the object. It's not principially different from asking
a (list-)object if it is empty(), and do something appropriate
in each case.

It is different, inherently so, in that type assertions normally should be done at compile time, and are less expensive to aver at that time, but listemptiness is inherently a run-time issue, being based on data and not the program's own types.
Thanks for pointing out the trick with generics, even though
it doesn't yet fully work. I hadn't thought of that, and might
run into a situation where it could prove useful.

It does "fully work", if the problem is fully thought out.
 
A

Andreas Leitgeb

Lew said:
Andreas said:
Lew said:
Andreas Leitgeb wrote:
Lew wrote:
Volker Borchert wrote:
if (l instanceof RandomAccess) {
Tests on type like this are an antipattern.
Are marker-interfaces (which RandomAccess is, iirc) already an
antipattern, or is there a different way to check for them, [...]
With generics you can use type intersections so that something has to be
both 'List' and 'RandomAccess' (again, say) even to reach the call or the
class or whatever.
Interesting stuff! (but still falls a bit short):
public static <T extends List,RandomAccess> T method(T raAcList) {
// public static <T extends List> T method(T anyList) {
You cannot have two erasure-equivalent methods in the same class, ...

It isn't obvious to me, how these really *need* to be erasure-equivalent.
I mean, obviously they are, but that's just a fact of Java as it is,
not a principial necessity.
If Java had a consistent model of intersection types even outside
of generics, like "List & RandomAccess raList = new ArrayList();",
then the erased type of first method()'s "T" would be just that
intersection type, and the methods would be obviously erasure-
*un*equivalent.
No need to tell me it ain't so. I know. :-(
The generics trick is suitable when you want to insist
that the argument be of the particular type, not when
you want to bifurcate as you indicated.

But bifurcation was the context of this discussion about
"instanceof"-red flags!
It seems as though perhaps you are in a situation where you
want to fork on the type at run-time, ...

Well, not me. See Volker's posting up-thread for the context
in which he suggested use of "instanceof".

Forking on "implementing or not implementing a particular
marker-interface" is an entirely different situation from
asserting a particular interface/type. I'm all with you
that the latter be done at compile-time whenever even
remotely possible.

Now, would you call "instanceof" in the specific context of
bifurcation (with none of the branches just barfing) still
a red flag?
 
L

Lew

Andreas said:
Lew said:
Andreas said:
Lew wrote:
Andreas Leitgeb wrote:
Lew wrote:
Volker Borchert wrote:
if (l instanceof RandomAccess) {
Tests on type like this are an antipattern.
Are marker-interfaces (which RandomAccess is, iirc) already an
antipattern, or is there a different way to check for them, [...]
With generics you can use type intersections so that something has to be
both 'List' and 'RandomAccess' (again, say) even to reach the call or the
class or whatever.
Interesting stuff! (but still falls a bit short):
public static <T extends List,RandomAccess> T method(T raAcList) {
// public static <T extends List> T method(T anyList) {
You cannot have two erasure-equivalent methods in the same class, ...

It isn't obvious to me, how these really *need* to be erasure-equivalent.
I mean, obviously they are, but that's just a fact of Java as it is,
not a principial necessity.
If Java had a consistent model of intersection types even outside
of generics, like "List & RandomAccess raList = new ArrayList();",
then the erased type of first method()'s "T" would be just that
intersection type, and the methods would be obviously erasure-
*un*equivalent.
No need to tell me it ain't so. I know. :-(
Alas.
The generics trick is suitable when you want to insist
that the argument be of the particular type, not when
you want to bifurcate as you indicated.

But bifurcation was the context of this discussion about
"instanceof"-red flags!

And my point was that there often is a way to put that bifurcation into a compile-time structure rather than run time. Doing 'instanceof' is a red flag that the type analysis is incomplete and there may be a compile-time way to do it instead.
Well, not me. See Volker's posting up-thread for the context
in which he suggested use of "instanceof".

The generic "you".
Forking on "implementing or not implementing a particular
marker-interface" is an entirely different situation from
asserting a particular interface/type. I'm all with you
that the latter be done at compile-time whenever even
remotely possible.

Now, would you call "instanceof" in the specific context of
bifurcation (with none of the branches just barfing) still
a red flag?

Yes.
 
A

Arved Sandstrom

It's up to the implementor to meet guarantees with any interface, even
one that declares methods. The compiler can enforce the presence of
methods with particular signatures, but that's as far as it goes.
[ SNIP ]

That's absolutely true, no argument from me. Your example, which I
snipped, illustrates not only your point that the compiler cannot
guarantee that any number of implemented methods actually obey a
contract, but also the point that *if* an implementor *is* honouring the
contract that precisely zero methods are needed in the interface: hence
the usefulness of a marker interface.

AHS
 
A

Arved Sandstrom

Fair enough. If I was to write code that was supposed to work for both
types (with or without a particular marker interface), then in the part
for "no marker" (as statically determined) I'd better still add a runtime-
check for it. In theory, theory and practise are the same, in practise
they aren't. :)


I wonder, if that is done in practise. E.g.: do you happen to know code
in the Java Standard Library or other renowned project that does this kind
of static check for a marker-interface?
Bloch, in the previously mentioned Item 37 of Effective Java, calls out
Set as a so-called "restricted marker interface". Restricted because it
extends Collection, so isn't a "free" marker interface. Nevertheless, it
exhibits the compile-time features of a marker interface "as new type".

Since you insist on JDK examples, you might also want to read the bit in
Item 37 where Bloch explains how Serializable _could have been_ written
so as to take advantage of that marker interface statically rather than
at runtime. Sometimes an example of something done wrong carries more
weight than an example of something done right.

I don't think that you'll find a whole bunch of examples, let alone
examples in "renowned" projects...whatever those are exactly. Most Java
programmers have always equated "marker interface" in Java with
java.io.Serializable: that single example has effectively squelched
wider proper use of marker interfaces in the language.

AHS
 
S

supercalifragilisticexpialadiamaticonormalizeringe

That's absolutely true, no argument from me. Your example, which I
snipped, illustrates not only your point that the compiler cannot
guarantee that any number of implemented methods actually obey a
contract, but also the point that *if* an implementor *is* honouring the
contract that precisely zero methods are needed in the interface: hence
the usefulness of a marker interface.

I wasn't disagreeing with you; just noting that marker interfaces aren't
a special case here. It's always on the honor system, whether there are
methods specified or not, so any objection to marker interfaces boiling
down to "there's nothing in the contract for the compiler to enforce!"
is specious, IMO, as what there is for the compiler to enforce in other
interfaces is but the tip of the proverbial iceberg anyway. In fact the
main job of method specifications in those isn't contract enforcement,
it's linkage, so the compiler can set up/anticipate the appropriate
vtable entries and the loader can hook all the calls up properly for
efficient runtime invocation. For that, a side effect is to make the
compiler enforce that certain methods be present in the implementing
class, which does enforce a tiny bit of the contract, but that's
basically just a small bonus. Another reason for method specifications
that is of higher significance than *enforcing* (a bit of) the contract
is that of *documenting* (a bit of) the contract.
 
A

Andreas Leitgeb

Arved Sandstrom said:
Since you insist on JDK examples, you might also want to read the bit in
Item 37 where Bloch explains how Serializable _could have been_ written
so as to take advantage of that marker interface statically rather than
at runtime.

Sounds interesting (I'll ask colleagues if they have a copy of that
book) but not entirely relevant for RandomAccess. There typically
is no "plan B" for code that expects a serializable object but got
a non-s'able one.

Making things static is a good means to detect *errors* earlier,
namely at compile-time. For that it is also worth some effort
like duplicating other methods (that pass through objects, but
do not care about serializability, themselves) for both variants
to preserve the static information. I don't yet see the benefit
of making decisions between "plan A" and "plan B" static if
neither is an error.

If the answer is "performance", I'm tempted to refer to Item 37
in the *first* Edition of above-mentioned book.
 
A

Andreas Leitgeb

Lew said:
And my point was that there often is a way to put that
bifurcation into a compile-time structure rather than
run time.

For classes I design myself: yes. It's called "virtual
methods" and is a standard feature of Java ;-)

That just isn't an option for foreign library classes
if the "bifurcation" happens in my own code.

I'm still eager to see an alternative to "instanceof"
for the RandomAccess-case.
 
S

supercalifragilisticexpialadiamaticonormalizeringe

For classes I design myself: yes. It's called "virtual
methods" and is a standard feature of Java ;-)

That just isn't an option for foreign library classes
if the "bifurcation" happens in my own code.
....

I'm still eager to see an alternative to "instanceof"
for the RandomAccess-case.

I wonder what the odds are of Java 8 adding a variant of switch/case
like this?

switch class (object) {
case java.util.RandomAccess:
// code goes here
break;
case java.util.List:
// code goes here
break;
// ...
case null:
// code for if object is null goes here
break;
default:
// code goes here
}

For when you don't control the classes yourself, but need to dispatch on
their type in new code. It could compile into something as efficient as
an invokevirtual, or nearly so, e.g. a jump through a hashed lookup
table keyed by the object's hidden class field. The commonest use case
would undoubtedly be in implementing equals methods in hierarchies that
have mutually comparable subclasses, and the second commonest would be
strategy dispatch like you wanted with RandomAccess the deciding factor,
and maybe also clearly breaking out "if null" special cases.

The other way to implement something like this would be a run-time
overload resolution option, say something like:

public volatile int method (RandomAccess list) { ... }
public volatile int method (List list) { ... }
public volatile int method (null) { ... }

Hypothetically, the compiler basically turns this into a single method
accepting type List with the above switch inside, minus default clause,
and with the type of "list" being cast as appropriate inside the code
blocks.

Alternatively, just call it double dispatch. :) The null case has no
local variable "list" available. Either every overload of "method" is
"volatile", none are, or it's an error. The added dispatch is on the
type of the first argument, and it must be a reference type. The most
specific matching type is chosen, and if there are two equally specific
alternatives this is a run-time error, but a parameter type of
(Interface1 && Interface2) or similar is permitted to add an
intersection case to alleviate such errors. A new RuntimeException
subclass AmbiguousDispatchException can be added for that case.
Alternatively, it could be a compile-time error for there to be two
interface dynamic overloads but no intersection overload. Alternatively,
the "default" keyword could be added somewhere to make one of two
interface overloads preferred over the other when both matched. I'd
expect that to be rare, though, as the common-case choices would be over
concrete classes or a family of related successively narrower interfaces.

As near as I can tell, none of the above proposed syntax extensions
breaks backwards source compatibility or requires class format/JVM
changes to implement; just javac enhancements.
 
A

Andreas Leitgeb

I wonder what the odds are of Java 8 adding a variant of switch/case
like this?
switch class (object) {
case java.util.RandomAccess:
// code goes here
break;
[...]

If you ask for my opinion: zero.

The particular usecase that RandomAccess is used for is in my
humble opinion merely a syntactic trick almost same as defining
a boolean getter in each relevant class that would merely return
constantly true or constantly false depending on whether the
implementing class has a certain property or not.

This particular misuse makes it necessary to use instanceof
just as the syntax for querying the property.

Sweetening this particular misuse of interfaces with some
additional syntactic sugar is so very the wrong way, that
I really don't want say much more about it.
 
A

Andreas Leitgeb

Andreas Leitgeb said:
The particular usecase that RandomAccess is used for is in my
humble opinion merely a syntactic trick almost same as defining
a boolean getter ...

Why do things suddenly mean something entirely different when I
read my own post later than what it meant to me when I wrote it? ;-)

I meant to say: almost to the same effect as defining ...

Defining a method surely isn't a "syntactical trick" (as it
would have been implied by my misformulation).
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top