接口 f 方法 f 实现类 g 实现接口方法 自定义方法 g
F f= new g();
f.g()不到,如何解释
向上转型为什么会丢掉g();
public interface F {
public void f();
}
public class G implements F {
public static void main(String []args) {
F g=new G();
g.g(); //这个方法看不到呢,如何解释
}
public void g(){
}
public void f(){
// TODO Auto-generated method stub
}
}
接口G实现了F
但是你是把一个G的实例,送给了F的引用,向上转型的时候丢失掉了g();
如果你想 g.g();调用成功的话,用强制转型 ((G)g).g();
补充:
首先类G是实现F的!看的普通一点,可以看成G是继承F的。这么理解下。
既然G是实现(继承)F的,那么F中的方法,自然被继承到了。但是G中可以定义自己的方法。这是没有疑问的。
JAVA中的多态机制却允许基类的引用指向子类的实例。因为基类中没有子类的方法,所以在这个过程中,子类的方法被扔掉。
同理,用到这个地方。 G中g()是G自己有的,F没有,那么向上(基类)转型过程中,g()被扔掉了。这就是所谓的向上转型丢失某些方法;
因为不丢掉的话,那就意味着,子类能给父类增添方法,这显然是不合乎道理的!!父类的方法只有自己增加
经常见
List<?> list= new ArrayList<?>
Map<?,?> map = new HashMap<?,?>
但是发现list只是ArrayList的接口不是它的父类 ,不是父类引用指向子类对象
如果是应该是AbstractLIst ablist= new ArraryList(); 或者直接写为ArrayList<?> list= new ArrayList<?>
为什么要用接口引用指向实现类的对象
这种写法其实Java多态的表现形式
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
List list;是在栈区开辟一个空间放list引用,并没有创建对象所以不知道ArrayList还是LinkedList当你list= new ArrayList(); 就创建了ArrayList对象。并且把开始创建的list引用指向这个对象ArrayList和LinkedList都是List的实现类。
为什么一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
问题就在于List有多个实现类,如 LinkedList或者Vector等等,现在你用的是ArrayList,也许哪一天你需要换成其它的实现类呢?,这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。假设你开始用 ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了 ArrayList特有的方法和属性。 ,如果没有特别需求的话,最好使用List list = new LinkedList(); ,便于程序代码的重构. 这就是面向接口编程的好处
注意事项
list只能使用ArrayList中已经实现了的List接口中的方法,ArrayList中那些自己的、没有在List接口定义的方法是不可以被访问到的
list.add()其实是List接口的方法
但是调用ArrayList的方法如 clone()方法是调用不到的
接口的灵活性就在于“规定一个类必须做什么,而不管你如何做”。我们可以定义一个接口类型的引用变量来引用实现接口的类的实例,当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法,这和上述的超类对象引用访问子类对象的机制相似。