java刷题2020年9月12日
-
下列程序执行后结果为( )
class A { public int func1(int a, int b) { return a - b; } } class B extends A { public int func1(int a, int b) { return a + b; } } public class ChildClass { public static void main(String[] args) { A a = new B(); B b = new B(); System.out.println("Result=" + a.func1(100, 50)); System.out.println("Result=" + b.func1(100, 50)); } }
正确答案: A 你的答案: C (错误)
Result=150Result=150 Result=100Result=100 Result=100Result=150 Result=150Result=100 解释: 其实很简单,涉及转型的题目,分为向上或者向下转型。 关键的来了,不论向上或者向下转型,都是一句话,“编译看左边,运行看右边”。也就是编译时候,会看左边引用类型是否能正确编译通过,运行的时候是调用右边的对象的方法。 就本题来说,编译时候会发现左边满足条件所以编译通过,运行时候又会调用右边也就是 class B 的方法,所以答案都是150。 此题考查的是多态。 对于多态,可以总结它为: 一、使用父类类型的引用指向子类的对象; 二、该引用只能调用父类中定义的方法和变量; 三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用) 四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。 多态的3个必要条件: 1.继承 2.重写 3.父类引用指向子类对象。 向上转型: Person p = new Man() ; //向上转型不需要强制类型转化 向下转型: Man man = (Man)new Person() ; //必须强制类型转化
-
list和set、map的比较: 1. List 是一个有序集合,可以存放重复的数据 (有序:存进是什么顺序,取出时还是什么顺序) (1).ArrayList 底层是数组适合查询,不适合增删元素。 (2).LiskedList 底层是双向链表适合增删元素,不适合查询操作。 (3).Vector 底层和ArrayList相同,但是Vector是线程安全的,效率较低很少使用 2. Set 是一个无序集合,不允许放重复的数据 (无序可重复,存进和取出的顺序不一样) (1).HashSet 底层是哈希表/散列表 (2).TreeSet 继承sartedSet接口(无需不可重复,但存进去的元素可以按照元素的大小自动排序) 3. Map 是一个无序集合,以键值对的方式存放数据,键对象不允许重复,值对象可以重复。 (1).HashMap实现不同步,线程不安全。 HashTable线程安全 (2).HashMap中的key-value都是存储在Entry中的。 (3).HashMap可以存null键和null值,不保证元素的顺序恒久不变,它的底层使用的是数组和链表,通过hashCode()方法和equals方法保证键的唯一性
-
以下代码执行后输出结果为( )
public class ClassTest{ String str = new String("hello"); char[] ch = {'a','b','c'}; public void fun(String str, char ch[]){ str="world"; ch[0]='d'; } public static void main(String[] args) { ClassTest test1 = new ClassTest(); test1.fun(test1.str,test1.ch); System.out.print(test1.str + " and "); System.out.print(test1.ch); } }
正确答案: A 你的答案: D (错误)
hello and dbc world and abc hello and abc world and dbc 解释: java中都是按栈中的值传递,基本数据类型栈中的值就是实际存储的值,引用类型栈中的值就是指向堆中的地址 1)String和char[ ]都是引用类型,所以在方法中传递的都是指向真实数据的地址 2)假设String str指向的hello的地址为d1,str传递到fun函数中的也是地址d1,成员变量str和fun的形参str不是同一个变量,把fun型中的str赋值为world只是修改了该str指向的地址,该地址由d1更改成了world的地址,并没有改变成员变量str指向的地址及堆中的数据,所以str还是hello。 3)假设char[ ] ch指向的abc的地址是d2,传递到fun函数中的地址也是d2,同上成员变量ch和fun的形参ch不是同一个变量,(1)如果把fun中的ch[0]='d'更改为ch = new ch[3];ch[0]='d',那么成员变量ch的值是没有变化的,还是abc,原理同上String,只是改变了引用ch指向的堆数据的地址,并没有改变成员变量ch指向的地址以及堆中的数据。(2)改变了堆中的数据,所以最终结果编程dbc,此ch只是形参而不是成成员变量ch,如果对ch变化对成员变量ch没有影响,但是ch[i]指向了堆数据的地址,直接修改堆数据,所以成员变量变了。
-
final、finally和finalize的区别中,下述说法正确的有?
正确答案: A B 你的答案: A B D (错误)
A final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 B finally是异常处理语句结构的一部分,表示总是执行。 C finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源的回收,例如关闭文件等。 D 引用变量被final修饰之后,不能再指向其他对象,它指向的对象的内容也是不可变的。 解释: 选AB A,D考的一个知识点,final修饰变量,变量的引用(也就是指向的地址)不可变,但是引用的内容可以变(地址中的内容可变)。 B,finally表示总是执行。但是其实finally也有不执行的时候,但是这个题不要扣字眼。 1. 在try中调用System.exit(0),强制退出了程序,finally块不执行。 2. 在进入try块前,出现了异常,finally块不执行。 C,finalize方法,这个选项错就错在,这个方法一个对象只能执行一次,只能在第一次进入被回收的队列,而且对象所属于的类重写了finalize方法才会被执行。第二次进入回收队列的时候,不会再执行其finalize方法,而是直接被二次标记,在下一次GC的时候被GC。