Java之多态与集合的那些事
public class A {
public void eat(){
System.out.println("this is A's eat way");
}
}
public class B extends A {
@Override
public void eat() {
System.out.println("this is B's eat way");
}
}
public class C extends A {
@Override
public void eat() {
System.out.println("this is C's eat way");
}
}
第一点 数组中的多态:
假设class B extends class A,对于数组来说,方法takeTesting中参数声明为父类A数组,但是此方法在执行eat时,是可以区分A和B的对象的

out put:

第二点ArrayList中的多态(1),当传入和声明一样的参数类型时
我们仅对go()方法和takeTesting做修改,调用takeTesting 方法也是可以正确识别A或者B对象的
public class D {
public void go() {
ArrayList<A> alist = new ArrayList<A>();
alist.add(new B());
alist.add(new A());
takeTesting(alist);
}
private void takeTesting(ArrayList<A> aa) {
for (A a : aa) {
a.eat();
}
}
public static void main(String[] args) {
new D().go();
}
}
依旧返回
this is B's eat way
this is A's eat way
第三点ArrayList中的多态(2),当传入和声明不一样的参数类型时,就会编译不通过
假设class B extends class A ,那么当声明 List<A>时,传参数就不能用List<B>

为什么会这样呢?--》假如编辑器允许上面操作的话,那么下面这段代码就有问题了,理论上把C对象加到ArrayList<A>是合法的,但如果我们允许传入一个B的ArrayList给该方法,那么结果就是一个被C给混进去的B集合,原本不可能出现的C的ArrayList<B>在这种情况下就出现了,这就是为什么编译器不让这种通过的原因!!
所以,如果把方法声明成取ArrayList<A>,他就只能取用ArrayList<A>参数,ArrayList<B>和ArrayList<C>都不行,此处没有多态的位置
private void takeTesting(ArrayList<A> aa) {
aa.add(new C());
}
同样的问题,还出现在ArrayList声明的时候,如下

可以再深入探讨下,以下对于数组的参数应该也有同样问题->
public static void main(String[] args) {
new D().go();
}
private void takeTesting(A[] alist) {
alist[0] = (new C());
}
public void go() {
B[] blist = {new B(),new B()};
takeTesting(blist);
}
//把C加到B的数组里,虽然骗过了编译器,但是会在运行时报错:Exception in thread "main" java.lang.ArrayStoreException: kevinDemo.C
所以,我们可以发现,数组的类型是在运行期间检查的,而集合的类型检查只会发生在编译期间
语法小坑:以下用list的add方法往集合中加值这种写法是不能出现在类的声明中的,方法的调用只能放在方法中,要不然最后编译后,这个add方法的执行就是类似
new D().list.add()--> 这肯定是错误的,因为list不是D对象的属性,不能用dot符号去引用

继续 集合的几种赋值方式->
ArrayList 的几种赋值方法:
List<String> list = new ArrayList<String>();
String str01 ="test1";
String str02 = "test2";
list.add(str01);
list.add(str02);
方式二:List<String> list = new ArrayList<String>(){{add("test1"); add("test2");}};
再用forEach 遍历出来
list.forEach(item->System.out.println(item));
方式三:
List<String> list = new ArrayList<>(Arrays.asList("test1","test2"));
OR
List<String> myList = Arrays.asList("Apple", "Orange");
最后一个方法的myList是个固定大小的数组因为
asList 返回一个由指定数组生成的固定大小的 List。
这里有比较两个list是否相同,其实两个list只是内容相同,但是是两个不同对象,为什么会equals相等呢,这个要从ArrayList的equals方法 说起,
equals方法内部在对列表元素进行逐个比较时,调用了元素的equals方法,这里其实就是调用了String的equals 方法,因为String有覆盖这个equals方法,所以上面语句才会返回true,
当然我们也可以根据需求对列表元素的equals方法进行重写,实现自己的比较逻辑
1 public boolean equals(Object o) {
2 if (o == this)
3 return true;
4 if (!(o instanceof List))
5 return false;
6
7 ListIterator<E> e1 = listIterator();
8 ListIterator e2 = ((List) o).listIterator();
9 while (e1.hasNext() && e2.hasNext()) {
10 E o1 = e1.next();
11 Object o2 = e2.next();
12 if (!(o1==null ? o2==null : o1.equals(o2)))
13 return false;
14 }
15 return !(e1.hasNext() || e2.hasNext());
16 }
浙公网安备 33010602011771号