List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);//结果输入 [1, 2, 3] 根据多态性 list对象调用方法时 只能调用List接口中定义的或从父接口中继承的方法
其中toString()好像不在其和其父接口之中吧
为什么
System.out.println(list)时会输出
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);//结果输入 [1, 2, 3] 根据多态性 list对象调用方法时 只能调用List接口中定义的或从父接口中继承的方法
其中toString()好像不在其和其父接口之中吧
为什么
System.out.println(list)时会输出
解决方案 »
- 以下数据库分页程序,为什么会出错
- 高手给看一下这个代码(100行)左右,就是一个timer计时器,运行时发现按下停止按钮后时间没归零
- 关于并行计算
- 如何在程序中实现鼠标点击jtextfield这一效果?
- 寻找java练习题.......50分,马上给分
- 【后空翻四周落地爬求】随机产生大素数的算法!
- 很奇怪的问题,各位请看!
- 请问平时用java开发应用程序,各位最常用也是最好用的是什么工具,java开发出的软件可以像VB开发的那样做安装程序吗?安装程序复杂吗?
- C语言是有函数组成 那Java是由什么组成的 ------类 ? 请问
- 请教多国文字问题:怎么设定awt才能同时显示简体,繁体,日文的unicode文字?
- 关于Servlet的生命周期方法init和destroy
- 关于小数位数的问题。
而toString是Object类的方法。
在 java.util.List 下没有
//等同于
System.out.println(list.toString());
/*
这里面的list.toString()方法,实际上,调用的是
ArrayList对象的toString()方法。
*/首先,List接口没有toString方法,所以,问题不在List接口上。
你调用的toString方法不是List要求实现的方法。
其次,在Java当中,所有的类,都默认继承Object类,并且,Object类中,有toString方法。
ArrayList作为一个类,也默认继承Object类,并且,实际当中,它重写了toString方法。
最后,调用toString方法,并没有展现List的多态性,而是Object的多态性。
其默认的toString实现,是返回JVM的对象地址,但是,很多对象都重写该方法,从而表现不同。
比如:Integer返回的是数字内容;StringBuilder返回的是当前缓冲区内存放的字符串;
ArrayList返回的是当前集合当中所有对象的toString结果;等等。
List是抽象的,当然没办法实例化。
作为ArrayList对象,继承自Object类,自然有toString方法。
明明java.util.List 中没有 toString() 却还是能执行 我再说个吧
Collection list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.toString());这个的输出结果也是 [1, 2, 3] 然而如果你调用 ArrayList 中的get()方法
即list.get(index) 就会出错
原因是 The method get(int) is undefined for the type Collection这个情况 难道和 list.toString() 有什么不一样的地方吗 不应该都是 没有定义该方法吗
所以也就重载了object的toString()方法
你可以查看JDK API文档,
能够发现ArrayList对象的继承关系如下:
java.util
Class ArrayList<E>
java.lang.Object
java.util.AbstractCollection<E> (找到toString(),所以ArrayList调用的是此方法)
java.util.AbstractList<E> (未找到toString()方法,继续上推)
java.util.ArrayList<E>
其中抽象类AbstractCollection的重写了Object对象的toString方法,代码如下:public String toString()
{
StringBuffer stringbuffer = new StringBuffer();
stringbuffer.append("[");
Iterator iterator1 = iterator();
boolean flag = iterator1.hasNext();
do
{
if(!flag)
break;
Object obj = iterator1.next();
stringbuffer.append(obj != this ? String.valueOf(obj) : "(this Collection)");
flag = iterator1.hasNext();
if(flag)
stringbuffer.append(", ");
} while(true);
stringbuffer.append("]");
return stringbuffer.toString();
}
java.util.AbstractCollection<E> (找到toString(),所以ArrayList调用的是此方法)
java.util.AbstractList<E> 这个对List接口实现了AbstractList<E>
AbstractList<E>继承自AbstractCollection<E> 有toString 方法。Collection 类并没有get方法。list.get()
Collection类的引用list自然无法调用get()方法了。
List list = new ArrayList();
list.get()是会调用ArrayList里面的get方法吧?
因为引用list指向的是ArrayList对象,
是不是多态有什么法则的。
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);
在打印的时候虚拟机会自己去调用.toString()方法;
toString()方法是Object对象的一个方法,所有类都直接或者间接的继承他,而且你不写他默认继承,
我所列出JDK源码中ArrayList的继承关系已经说的非常清楚了。
AbstractCollection<E>是一个抽象类,它重写了toString方法。
Collection list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.toString());
输出结果为 [1, 2, 3] Collection list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list.get(1));
会报错 The method get(int) is undefined for the type Collection红色标记的两个方法是不是在 ArrayList 中或其父类中都有
为什么第一个对 第二个却 说没有这个方法这不是多态的范畴吧
要是正常的多态 应该是 上面两个都会报 没有该方法 的错误
public interface InterfaceA {}//AbstractB(相当于那个AbstractCollect类)实现InterfaceA
public abstract class AbstractB implements InterfaceA {
public String toString(){//覆盖Object的方法
return "AbstractB";
}
}public class ClassC implements InterfaceA{
public static void main(String[] args) {
InterfaceA cc=new ClassC();
System.out.println(cc.toString()); //调用的是Object的方法(因为ClassC隐含继承Object)
//cc.get(); //报错,因为Object和InterfaceA中都找不到
}
}public class ClassD extends AbstractB{
public static void main(String[] args) {
InterfaceA dd=new ClassD();
System.out.println(dd.toString()); //调用的是AbstractB的方法()
//dd.get(); //报错,因为Object和AbstractB及InterfaceA中都找不到
}
}很明显ClassD和ArrayList的继承关系相似,而非ClassC.
JDK API中也指出了抽象类AbstractCollect实现了Collect接口。
二是,涉及到了多态。因为每个类的toString()实现方法不一样,不过这个和lz要的结果没有关系。
Collection接口没有get方法
List接口有
ArrayList实现了这两个接口
public class ClassD extends AbstractB{
public static void main(String[] args) {
InterfaceA dd=new ClassD();
System.out.println(dd.toString()); //调用的是AbstractB的方法()
//dd.get(); //报错,因为Object和AbstractB及InterfaceA中都找不到
}
}其实AbstractB也隐含继承Object.但它重写了toString方法。
又由于接口和抽象类都是不能实例化的,所以使用更上层的接口做为超类声明时,最终的具体子类在初始化时,都会先递归完成所有祖先类的初始化工作。在最终方法的调用时,如果自身不存在,则通过逐层查找,总是查找最近层父类中的相关方法。如果追到源头Object也没有,那就真没有了。
这里有一点新东西,好像是没有语法书上写出来的(也可能是我读的太少吧),但我通过实验得出来以下结论。
那就是,如果一个接口被实例化,那么,这个接口将自动继承object类中未被重写的方法。
以你的代码中的list为例,该接口最终不仅拥有toString()方法,而且还拥有object类当中的
三个wait方法以及notify(),notifyAll(),getClass()方法。
list接口当中总共25个方法,但是在本次代码中,实例化之后,却拥有了32个方法,增加的七个方法正是如上所述的七个方法。
但是为什么object当中还有clone,和finalize方法没有被list继承呢?我想应该是因为ArrayList类或者它的父类已经将该方法实现。
所以我的结论是“这个接口将自动继承object类中未被重写的方法”
注:实验工具Eclipse自动补充解析功能
所以:
用Collect声明时,ArrayList对象调用的不是接口调用的Object中的toString,而是调用的AbstractCollect中重写的方法。
由超类声明,子类来new.调用的最终是子类中定义的方法,如果子类没有,则调用父类方法。
这存在一种向上追溯的过程。
这也就是为什么Collect下还有一个抽象类AbsctratCollect这仍是多态的表现。故:
我重新支持自己在20楼及23楼中的说法。
24楼的话取消。
//相当与Collection
public interface InterfaceA {}//AbstractB(相当于那个AbstractCollect类)实现InterfaceA
public abstract class AbstractB implements InterfaceA {
public String toString(){//覆盖Object的方法
return "AbstractB";
}
public void get(){
System.out.println("AbstraceB get()");
}}
//相当于ArrayList
public class ClassD extends AbstractB{
public static void main(String[] args) {
InterfaceA dd=new ClassD(); System.out.println(dd.toString()); //调用的是AbstractB的方法()
dd.get(); //报错,因为Object和AbstractB及InterfaceA中都找不到
}
}InterfaceA中没有定义get() AbstractB 中定义了get() ClassD 中调用get()会报错 InterfaceA dd=new ClassD();
dd.get(); //这次在AbstractB 中可以找到了吧编译时dd只能看见InterfaceA中定义的和其父和祖宗接口中声明的方法 因为之中没有 get() 所以报错。虽然AbstractB 中有get() ClassD继承AbstractB 又能怎样
在本例中 ClassD中没有get() 它可以调用AbstractB 中的get()的前提是 InterfaceA 中或祖宗接口中有get()的声明
如果没有 连编译这一关就过不了相比之下
InterfaceA中没有声明 toString() 且它的父接口和祖宗接口中也没定义可以看API
却可以通过编译而且执行所以我觉得吧 Object这个类 还有它中的方法 反正就是不能按常理来推 比较特殊 里面肯定有更深的东西。
要么就是 我对多态的理解还不够
楼主懂得思考,先表扬一下。下面将引用一段接口的说明,你可以看看:9.2 Interface Members
The members of an interface are:Those members declared in the interface.
Those members inherited from direct superinterfaces.
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface. It is a compile-time error if the interface explicitly declares such a method m in the case where m is declared to be final in Object.
一个接口中的方法有:
1).直接声明在接口中的成员方法;
2).直接从父类接口中继承而来的方法;
3).如果一个接口没有直接的父类接口(也就是其自身就是顶层接口),并且在其没有显示声明相关方法时,那该接口则会根据Object中所有的public的实例方法进行一一映射(比如toString,Hashcode等)。当然如果此接口显示去声明一个与Object签名相同并且带有final修饰的方法时,则会有编译期错误。
这存在一种向上追溯的过程。的说明是完全正确的。
这里做一点补充。
根据这一条说明,在List list=new ArrayList()之后,在list当中将可以调用object当中所有声明public的方法,而调用的方法实体是来自ArrayList的。而之所以没有list不可以调用,clone()与finalize()方法,只是因为它们是protected的。
学习了。
不过很好奇,33楼的大哥,这条如此原版的声明出自哪个参考书籍呢?学java就该看这种资料啊。