Java基础刷题指南 Posted on 2020-09-09 | Edited on 2023-05-09 | In java | Views: 刷题来自牛客网。lee 的错题记录。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921. 说法正误在java中,无论在何处调用,使用静态属性必须以类名做前缀。//false。//1如果是本类使用,可以直接就用静态变量名。2如果是其他类使用,可以使用类名来调用,也可以创建一个实例对象来调用。3如果静态变量所在的类是静态类,那么不管在本类里或者在其他外部类,都可以直接使用静态变量名。2. 说法正误在方法中定义的局部变量在该方法被执行时创建。//false。//不是局部变量在该方法被执行/调用时创建,而是应该为在该变量被声明并赋值时创建,可以理解为“当代码执行到该变量被赋值的代码时才被创建”。3. 语法正误public abstract final class Test { abstract void method(); // false。final修饰的类为终态类,而抽象类是必须被继承的才有其意义的。所以 final 不能用来修饰抽象类的。}public abstract class Test { abstract final void method(); //false。final修饰的方法为终态方法,不能被重写,而继承抽象类,必须重写其方法。}public abstract class Test { abstract void method() { // false。抽象方法是仅声明,并不做实现的方法。 }}public class Test { final void method() { // true }}4. 结果正误String str1="hello";String str2="he"+ new String("llo");System.out.println(str1==str2); // false。str1 指向字面量“hello”,这里的str2必须在运行时才知道str2是什么,所以它是指向的是堆里定义的字符串“hello”// new String("llo")在编译期时创建一个“llo”的字面量(在 String pool 中),在运行期执行new命令创建另一个“llo”(在堆中)//String s = "a"+"b"+"c"; 语句中,“a”,"b", "c"都是常量,编译时就直接存储他们的字面值,而不是他们的引用,在编译时就直接将它们连接的结果提取出来变成"abc"了。5. 语法正误public class Test{ private float f = 1.0f; int m = 12; static int n = 1; public static void main (String args[]){ Test t = new Test(); t.f;//true。因为main函数在该类中,所以即使private也仍可使用 this.n;//false。this不能在static的方法中使用 Test.m;//false。m 和 f 都是普通成员属性 Test.f;//false。m 和 f 都是普通成员属性 }}6. 输出结果:public class CharToString { public static void main(String[] args) { char myChar = 'g'; String myStr = Character.toString(myChar); System.out.println("String is: "+myStr); myStr = String.valueOf(myChar); System.out.println("String is: "+myStr); }}output:String is: g // toString 和 valueOf 方法返回值都是 StringString is: g // 只有char变成 int 的时候才会变为对应的assic码7. 输出结果public static void main(String args[])throws InterruptedException{ Thread t=new Thread(new Runnable() { public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.print("2"); } }); t.start(); t.join(); System.out.print("1");}output:21 // thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。//t.join(); //使调用线程 t 在此之前执行完毕。//t.join(1000); //等待 t 线程,等待时间是1000毫秒8. 说法正误Hashtable 和 HashMap 的区别是: Hashtable 是一个哈希表,该类继承了 AbstractMap,实现了Map接口 // false。Hashtable 继承了Dictionary 类。 HashMap 是内部基于哈希表实现,该类继承AbstractMap,实现Map接口 // true。 Hashtable 线程安全的,而 HashMap 是线程不安全的 // true。 Properties 类 继承了 Hashtable 类,而 Hashtable 类则继承Dictionary 类 // true。 HashMap允许将 null 作为一个 entry 的 key 或者 value,而 Hashtable 不允许。// true。Hashtable 的key、value都不可以为null。// 另外,Hashtable 使用对象的hashCode,而 HashMap 重新计算 hash 9. 输出结果class Test { public static void main(String[] args) { System.out.println(new B().getValue()); } static class A { protected int value; public A (int v) { setValue(v); } public void setValue(int value) { this.value= value; } public int getValue() { try { value ++; return value; } finally { this.setValue(value); System.out.println(value); } } } static class B extends A { public B () { super(5); setValue(getValue()- 3); } public void setValue(int value) { super.setValue(2 * value); } }}output:22 34 17Step 1: new B()构造一个B类的实例 此时super(5)语句调用显示调用父类A带参的构造函数,该构造函数调用setValue(v),这里有两个注意点一是虽然构造函数是A类的构造函数,但此刻正在初始化的对象是B的一个实例,因此这里调用的实际是B类的setValue方法,于是调用B类中的setValue方法 ==> 而B类中setValue方法显示调用父类的setValue方法,将B实例的value值设置为2 x 5 = 10。 紧接着,B类的构造函数还没执行完成,继续执行setValue(getValue()- 3) // 备注1语句。 先执行getValue方法,B类中没有重写getValue方法,因此调用父类A的getValue方法。这个方法比较复杂,需要分步说清楚: 调用getValue方法之前,B的成员变量value值为10。 value++ 执行后, B的成员变量value值为11,此时开始执行到return语句,将11这个值作为getValue方法的返回值返回出去 但是由于getValue块被try finally块包围,因此finally中的语句无论如何都将被执行,所以步骤2中11这个返回值会先暂存起来,到finally语句块执行完毕后再真正返回出去。 这里有很重要的一点:finally语句块中 this.setValue(value)方法调用的是B类的setValue方法。为什么?因为此刻正在初始化的是B类的一个对象(运行时多态),就像最开始第一步提到的一样(而且这里用了使用了this关键词显式指明了调用当前对象的方法)。因此,此处会再次调用B类的setValue方法,同上,super.关键词显式调用A的setValue方法,将B的value值设置成为了2 * 11 = 22。 因此第一个打印项为22。 finally语句执行完毕 会把刚刚暂存起来的11 返回出去,也就是说这么经历了这么一长串的处理,getValue方法最终的返回值是11。 回到前面标注了 //备注1 的代码语句,其最终结果为setValue(11-3)=>setValue(8) 而大家肯定也知道,这里执行的setValue方法,将会是B的setValue方法。 之后B的value值再次变成了2*8 = 16;Step2: new B().getValue() B类中没有独有的getValue方法,此处调用A的getValue方法。同Step 1, 调用getValue方法之前,B的成员变量value值为16。 value++ 执行后, B的成员变量value值为17,此时执行到return语句,会将17这个值作为getValue方法的返回值返回出去 但是由于getValue块被try finally块包围而finally中的语句无论如何都一定会被执行,所以步骤2中17这个返回值会先暂存起来,到finally语句块执行完毕后再真正返回出去。 finally语句块中继续和上面说的一样: this.setValue(value)方法调用的是B类的setValue()方法将B的value值设置成为了2 * 17 = 34。 因此第二个打印项为34。 finally语句执行完毕 会把刚刚暂存起来的17返回出去。 因此new B().getValue()最终的返回值是17.Step3: main函数中的System.out.println 将刚刚返回的值打印出来,也就是第三个打印项:17 10. 输出结果package Test;public class Test { private static void test(int[] arr) { for (int i = 0; i < arr.length; i++) { try { if (arr[i] % 2 == 0) { throw new NullPointerException(); } else { System.out.print(i); } } finally { System.out.print("e"); } } } public static void main(String[]args) { try { test(new int[] {0, 1, 2, 3, 4, 5}); } catch (Exception e) { System.out.print("E"); } }} // 由于arr[0] =0,所以在进入 test()方法里面会在第一个if 上抛出一个 NullPointerException,接着会执行 finally 的语句, (finally语句先于 return 和 throw语句执行),输出一个'e,然后回到 main方法中,由于捕捉到异常,所以进入到catch语句中,然后打印一个'E',所以最终结果为"eE"11. 输出结果String str ="";System.out.print(str.split(",").length);output:1 // String split 这个方法默认返回一个数组,如果没有找到分隔符,会把整个字符串当成一个长度为1的字符串数组 12. 判断正误:关于Java中的ClassLoader 的描述:默认情况下,Java应用启动过程涉及三个ClassLoader: Boostrap, Extension, System // true, System加载器也称应用加载器一般的情况不同ClassLoader装载的类是不相同的,但接口类例外,对于同一接口所有类装载器装载所获得的类是相同的 // false类装载器需要保证类装载过程的线程安全 // trueClassLoader的loadClass在装载一个类时,如果该类不存在它将返回null //false,会直接报错ClassLoader的父子结构中,默认装载采用了父优先 // true所有ClassLoader装载的类都来自CLASSPATH环境指定的路径 // false,自定义类加载器实现继承ClassLoader后重写了findClass方法,所以会加载指定路径(程序员自定义的)上的class 13. 输出结果2009的2009次方,将结果各位数相加,得出结果如果不是一位数就继续各位相加,直到一位数,最后的结果是?output:5 // 数字各位相加相当于原数字对 9 取模,2009 % 9可以表示成(9x+2) % 9 = 2,而2009*2009可以表示成(9x+2)(9x+2) % 9 = (9y + 4) % 9 = 4,同理接下去可以表示成(9z+4)(9x+2) % 9 = 8,可以得到规律是2,4,8,7,5,1,那第2009次就是5了 -------------The End-------------