Java Forum / General / October 2005
How to know which interfaces an object implements?
Miguel Farah - 20 Oct 2005 00:05 GMT I'm writing a method that will receive as an argument an object (any object) and does some stuff depending on which class it belongs to or which interface it implements (in particular, wether it implements the java.util.List interface). To do that, I need to be able to discern that.
This is how I've solved it (replace the first line with whatever class you want):
Vector v=new Vector(); boolean implementsList=false; Class[] x=v.getClass().getInterfaces(); for (int k=0;k<x.length;k++) { if (x[k].toString().equals("interface java.util.List")) implementsList=true; } System.out.println(implementsList);
This actually works, but is very ugly, in my opinion. Is there a more elegant way to do the same?
Same goes for recognizing classes - I'm barely comfortable with:
if (v.getClass().getName().equals("java.util.Vector") { ....}
TIA.
klynn47@comcast.net - 20 Oct 2005 00:40 GMT Have you tried the reflection classes?
Thomas Fritsch - 20 Oct 2005 00:43 GMT > I'm writing a method that will receive as an argument an object (any > object) and does some stuff depending on which class it belongs to or [quoted text clipped - 12 lines] > implementsList=true; > } You can replace the above 6 lines by: if (java.util.List.class.isAssignableFrom(v.getClass())) or better by: if (v instanceof java.util.List)
> System.out.println(implementsList); > [quoted text clipped - 4 lines] > > if (v.getClass().getName().equals("java.util.Vector") { ....} You can this shorten to: if (v.getClass().equals(java.util.Vector.class)) { ....} or to:
if (v.getClass() == java.util.Vector.class) { ....} or by if (v instanceof java.util.Vector) { ....} The last variant is not exactly equivalent to yours, but probably what you really want, because it also accounts for v being an instance of a *sub*-class of Vector.
The 'xxxx.class' thing is called 'class literal'. You may want to read about it in the language spec. http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#251530 Explainations of the 'instanceof' operator can be found in every good Java text-book.
 Signature "TFritsch$t-online:de".replace(':','.').replace('$','@')
Roedy Green - 20 Oct 2005 01:36 GMT >This actually works, but is very ugly, in my opinion. Is there a more >elegant way to do the same? You read the javadoc. That is how mostly you discover the class hierarchies and interface implementations.
IDEs have features to show you that info quickly.
You can also just do a cast to a interface and see if you get a compile time or run time error.
You can also use instanceof
It depends on the context of your problem what is a reasonable way to solve it.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Thomas Weidenfeller - 20 Oct 2005 11:24 GMT > I'm writing a method that will receive as an argument an object (any > object) and does some stuff depending on which class it belongs to or > which interface it implements (in particular, wether it implements the > java.util.List interface). First of all, basing an application on such a design is a very bad idea without having a very, very good reason. The real solution would be to get rid of this stuff.
Second, if you need to test for the presence of an interface, simply use instanceof:
> Vector v=new Vector(); if(v instanceof List) { List l = (List)v; ... }
> if (v.getClass().getName().equals("java.util.Vector") { ....} if(c instanceof Vector) { ... }
But as a rule, whenever you need stuff like instanceof, consider changing your design. This is just glue which is useful to link things together with don't fit. Which is fine, if you have no control over the things which you need to glue together (e.g. external libraries), but which is bad if you have designed your own stuff in a way that it doesn't fit together.
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Miguel Farah - 20 Oct 2005 16:28 GMT > > I'm writing a method that will receive as an argument an object (any > > object) and does some stuff depending on which class it belongs to or [quoted text clipped - 5 lines] > get rid of this stuff. >[...] Thanks all for the help. Using the instanceof operator was easier and more straightforward than I gave credit to. Live and learn...
Now, on WHY I'm doing this:
I usually have to debug source code written by someone else, where faulty data provokes errors. Tracing those usually implies getting printouts of said data in a logfile, and then figure out the rest. Usually, the quickest way is to simply stick in a System.out.println() and execute... which leads to useless output like this example:
String[] c={"Hello", "world!"}; [...] System.out.println("data: <"+c+">");
The result is...
data: <[Ljava.lang.String;@16f0472>
Certainly not very useful.
So I wrote a method that would get in a String[] and spit back its entire content, like this:
System.out.println("data: <"+contentsOf(c)+">");
data: <{Hello, World!}>
Afterwards, I thought it would be better to write a method that would be able to do the same with hashtables, vectors... hell, ANY object. So far, I've implemented arrays, hashtables and lists (because that's what I encounter all the time). I just hope I'm not reinventing the wheel...
This method is part of a "String utilities" class we have here:
static public String contentsOf(Object o) { String s="";
if (o==null) { s="null";
} else if (o.getClass().isArray()) { s="{"; Object[] a=(Object[])o; for (int i=0; i<a.length; i++) { s+=contentsOf(a[i]) + ((i==a.length-1)?"":", "); } s+="}";
} else if (o instanceof java.util.List) { s+="["; List l=(List)o; for (int i=0;i<l.size();i++) { s+=contentsOf(l.get(i)) + ((i==l.size()-1)?"":", "); } s+="]";
} else if (o instanceof java.util.Hashtable) { s+="{"; Hashtable h=(Hashtable)o; for(Enumeration e=h.keys(); e.hasMoreElements(); ) { Object c=e.nextElement();
s+=contentsOf(c)+"="+contentsOf(h.get(c))+(e.hasMoreElements()?", ":""); } s+="}";
} else { s=o.toString();
} return s; }
Thomas Fritsch - 20 Oct 2005 17:39 GMT > I usually have to debug source code written by someone else, where > faulty data provokes errors. Tracing those usually implies getting [quoted text clipped - 11 lines] > > Certainly not very useful. Indeed! Instead of this you can use: System.out.println("data: " + Arrays.asList(c)); You'll get the result: data: [Hello, world!]
> So I wrote a method that would get in a String[] and spit back its > entire content, like this: [quoted text clipped - 8 lines] > far, I've implemented arrays, hashtables and lists (because that's what > I encounter all the time). I just hope I'm not reinventing the wheel... Sorry, you *are* reinventing the wheel. AbstractCollection (the super-class of Vector and others), AbstractMap (the super-class of HashMap and others) and Hashtable have already very smart toString() methods doing what you want. These toString() methods are automatically called by System.out.println(...). For example: List list = new Vector(); list.add("Hello"); list.add("world!"); System.out.println("list: " + list); results in: list: {Hello, world!}
Map map = new HashMap(); map.put("a","Hello"); map.put("b","world!"); System.out.println("map: " + map); results in: map: {a=Hello, b=world!}
 Signature "Thomas:Fritsch$ops:de".replace(':','.').replace('$','@')
Miguel Farah - 20 Oct 2005 18:21 GMT > > I usually have to debug source code written by someone else, where > > faulty data provokes errors. Tracing those usually implies getting [quoted text clipped - 15 lines] > You'll get the result: > data: [Hello, world!] That's indeed better, but still not enough to satisfy my convoluted mind. :-) Please see the examples below.
> > So I wrote a method that would get in a String[] and spit back its > > entire content, like this: [quoted text clipped - 10 lines] > > > Sorry, you *are* reinventing the wheel. I was afraid so. Or maybe it's a BETTER wheel? ;-)
> AbstractCollection (the super-class of Vector and others), AbstractMap > (the super-class of HashMap and others) and Hashtable have already very [quoted text clipped - 12 lines] > results in: > map: {a=Hello, b=world!} Yes, indeed. However, during my tests I quickly found limitations. The following segment of code:
----8<--------8<--------8<--------8<--------8<--------8<--------8<---- Object[] o1={"hola", "que", "tal"}; Object[] o4={new Integer(1), new Integer(2), new Integer(4)}; Object[] o5={"hola", null, "mundo", o4}; String[] s3={"a", null, "i ", "o", "u"};
String a="test"; Integer b=new Integer(123); String[] c={"Hello", null, "world!"}; Hashtable d=new Hashtable(); d.put("0", "oo"); Hashtable e=new Hashtable(); e.put("comp.lang", "java.programmer"); e.put("MIGUEL", "FARAH"); e.put("P", s3); e.put("Q", o5); e.put("H", d); Vector f=new Vector(); f.add("ASDF"); f.add(new Double(Math.PI)); f.add(e); f.add(d); f.add(e); // yup, again f.add(o1); Vector g=new Vector(); Hashtable h=new Hashtable(); h.put("1", "2"); h.put("a", "b"); h.put(new Double(3.14159), new Integer(-1)); h.put(new Vector(), new Hashtable()); Object[] i={null, null, null}; Object[] j={i, i};
System.out.println("contentsOf(a): <"+contentsOf(a)+">\n"); System.out.println("a.toString() : <"+a.toString() +">\n\n"); System.out.println("contentsOf(b): <"+contentsOf(b)+">\n"); System.out.println("b.toString() : <"+b.toString() +">\n\n"); System.out.println("contentsOf(c): <"+contentsOf(c)+">\n"); System.out.println("c.toString() : <"+c.toString() +">\n\n"); System.out.println("contentsOf(d): <"+contentsOf(d)+">\n"); System.out.println("d.toString() : <"+d.toString() +">\n\n"); System.out.println("contentsOf(e): <"+contentsOf(e)+">\n"); System.out.println("e.toString() : <"+e.toString() +">\n\n"); System.out.println("contentsOf(f): <"+contentsOf(f)+">\n"); System.out.println("f.toString() : <"+f.toString() +">\n\n"); System.out.println("contentsOf(g): <"+contentsOf(g)+">\n"); System.out.println("g.toString() : <"+g.toString() +">\n\n"); System.out.println("contentsOf(h): <"+contentsOf(h)+">\n"); System.out.println("h.toString() : <"+h.toString() +">\n\n");
System.out.println("contentsOf(i): <"+contentsOf(i)+">\n"); System.out.println("i.toString() : <"+i.toString() +">\n"); System.out.println("asList(i) : <"+Arrays.asList(i) +">\n\n"); System.out.println("contentsOf(j): <"+contentsOf(j)+">\n"); System.out.println("j.toString() : <"+j.toString() +">\n"); System.out.println("asList(j) : <"+Arrays.asList(j) +">\n\n"); ----8<--------8<--------8<--------8<--------8<--------8<--------8<----
produces the following output:
----8<--------8<--------8<--------8<--------8<--------8<--------8<---- contentsOf(a): <test>
a.toString() : <test>
contentsOf(b): <123>
b.toString() : <123>
contentsOf(c): <{Hello, null, world!}>
c.toString() : <[Ljava.lang.String;@16f0472>
contentsOf(d): <{0=oo}>
d.toString() : <{0=oo}>
contentsOf(e): <{comp.lang=java.programmer, MIGUEL=FARAH, H={0=oo}, Q={hola, null, mundo, {1, 2, 4}}, P={a, null, i , o, u}}>
e.toString() : <{comp.lang=java.programmer, MIGUEL=FARAH, H={0=oo}, Q=[Ljava.lang.Object;@5224ee, P=[Ljava.lang.String;@f6a746}>
contentsOf(f): <[ASDF, 3.141592653589793, {comp.lang=java.programmer, MIGUEL=FARAH, H={0=oo}, Q={hola, null, mundo, {1, 2, 4}}, P={a, null, i , o, u}}, {0=oo}, {comp.lang=java.programmer, MIGUEL=FARAH, H={0=oo}, Q={hola, null, mundo, {1, 2, 4}}, P={a, null, i , o, u}}, {hola, que, tal}]>
f.toString() : <[ASDF, 3.141592653589793, {comp.lang=java.programmer, MIGUEL=FARAH, H={0=oo}, Q=[Ljava.lang.Object;@5224ee, P=[Ljava.lang.String;@f6a746}, {0=oo}, {comp.lang=java.programmer, MIGUEL=FARAH, H={0=oo}, Q=[Ljava.lang.Object;@5224ee, P=[Ljava.lang.String;@f6a746}, [Ljava.lang.Object;@1e63e3d]>
contentsOf(g): <[]>
g.toString() : <[]>
contentsOf(h): <{3.14159=-1, a=b, 1=2, []={}}>
h.toString() : <{3.14159=-1, a=b, 1=2, []={}}>
contentsOf(i): <{null, null, null}>
i.toString() : <[Ljava.lang.Object;@1004901>
asList(i) : <[null, null, null]>
contentsOf(j): <{{null, null, null}, {null, null, null}}>
j.toString() : <[Ljava.lang.Object;@13e8d89>
asList(j) : <[[Ljava.lang.Object;@1004901, [Ljava.lang.Object;@1004901]>
----8<--------8<--------8<--------8<--------8<--------8<--------8<----
For the record, I'm still using Java 1.4.2 (we can't go to 1.5/5.0 yet).
Sure, the toString()/asList methods do their thing, but they don't go deep enough, IMHO.
I acknowledge that my examples are quite twisted, but I want to be able to handle ANYTHING that comes in my way. And considering the abysmal quality of the code delivered by some of the consultants that worked for us in the recent past (and I dare not say present), I'd rather be prepared.
Thomas Fritsch - 20 Oct 2005 19:17 GMT [...]
> Sure, the toString()/asList methods do their thing, but they don't go > deep enough, IMHO. > > I acknowledge that my examples are quite twisted, I agree ;-)
> but I want to be able > to handle ANYTHING that comes in my way. And considering the abysmal > quality of the code delivered by some of the consultants that worked > for us in the recent past (and I dare not say present), I'd rather be > prepared. I personally would not overhasty begin an endless series of curing symptoms without curing the underlying disease. In your case this might be: Make it a requirement for your blamed consultants to implement smart toString() methods in their classes, or better implement them yourself. (BTW: I assume you own their sources. Shame on you, if you don't)
 Signature "Thomas:Fritsch$ops:de".replace(':','.').replace('$','@')
Roedy Green - 21 Oct 2005 02:44 GMT >I personally would not overhasty begin an endless series of curing >symptoms without curing the underlying disease. In your case this might >be: Make it a requirement for your blamed consultants to implement smart >toString() methods in their classes, or better implement them yourself. >(BTW: I assume you own their sources. that is exactly what he did by posting here. Many eyes would have missed the cleverness already present in Collections. Yours did not.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Thomas Weidenfeller - 21 Oct 2005 08:50 GMT > I usually have to debug source code written by someone else, where > faulty data provokes errors. Tracing those usually implies getting > printouts of said data in a logfile, and then figure out the rest. > Usually, the quickest way is to simply stick in a System.out.println() > and execute... which leads to useless output like this example: You might consider learning to use a debugger instead of messing with println().
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Miguel Farah - 21 Oct 2005 19:33 GMT > > I usually have to debug source code written by someone else, where > > faulty data provokes errors. Tracing those usually implies getting [quoted text clipped - 4 lines] > You might consider learning to use a debugger instead of messing with > println(). Yeah, I could... but in my experience, they're not really useful (and as they grow more complex, the less usefulness they have). println()s are simpler to handle. YMWV.
Roedy Green - 22 Oct 2005 00:52 GMT >Yeah, I could... but in my experience, they're not really useful (and >as they grow more complex, the less usefulness they have). println()s >are simpler to handle. YMWV. Try out the one in Eclipse. It is not your father's Oldsmobile.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Again taking new Java programming contracts.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|