java基础知识点、面试选择题归纳整理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_30531261/article/details/79019550

前言

之前刷了一些题,为了方便自己日后可以快速的查缺补漏以及方便有需要的人,这里整理了一些个人感觉比较有意义的选择题,题目均来自牛客网的java相关选择题。
如各位看官发现哪里写的不对的,请帮忙指出,谢谢。
题目基本就更新完了(2018.01.30)
ps:答案设置成了白色字体,想要看答案,只需选中答案那一行即可看到答案。

正文

一、陷阱之i等于i自增

1.以下代码执行的结果显示是多少()?

public class Inc {
    public static void main(String args[]){
        Inc inc = new Inc();
        int i = 0;
        inc.fermin(i);
        i = i++;
        System.out.println(i);
    }
    void fermin(int i){
        i++;
    }
}

A. 0
B. 1
C. 2
D. 3

答案:A
笔记:
对于i=i++,先是执行i++,i自增1并返回自增前的值,因此如果i的初始值为0,那么执行i++,i变成1,并返回自增前的值,也就是0,再执行赋值操作,因此i=0。故先A。记住,遇到i=i++,i的值不变。

2.检查程序,是否存在问题,如果存在指出问题所在,如果不存在,说明输出结果()

public class Demo {
    public static void main(String args[]){
        int count = 0;
        int num = 0;
        for(int i=0;i<=100;i++){
            num = num+i;
            count = count++;
        }
        System.out.println(num*count);
    }
}

A. 505000
B. 0
C. 运行时错误
D. 5050

答案:B

二、正则表达式

1.Java中用正则表达式截取字符串中第一个出现的英文左括号之前的字符串。比如:北京市(海淀区)(朝阳区)(西城区),截取结果为:北京市。正则表达式为()
A. “.*?(?=\()”
B. “.*?(?=()”
C. “.*(?=\()”
D. “.*(?=()”

答案:A
笔记:
.表示匹配\n除外的任何字符,*表示匹配0个或多个,.*后接?表示非贪婪匹配,(?=pattern),即正向肯定预查,这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。因此(?=\\()表示匹配左括号。
正则表达式参考网址:http://www.runoob.com/regexp/regexp-metachar.html

2.关于下面的程序,哪一个选项是正确的输出结果()

    public static void main (String[] args) { 
        String classFile = "com.jd.". replaceAll(".", "/") + "MyClass.class";
        System.out.println(classFile);
    }

A. com. jd
B. com/jd/MyClass.class
C. ///////MyClass.class
D. com.jd.MyClass

答案:C
笔记:
public String replaceAll(String regex,String replacement),有该方法的声明可知第一个参数是regex,即表示正则表达式的字符串,而在正则表达式中,”.”表示的是除\n外的任意字符,因此原字符串中的”com.jd.”都会被替换成”/”,如果想要达到正确的结果,则需要使用转移符号,即改成:replaceAll(“.”, “/”),这样就能得到”com/jd/MyClass.class”这个结果。

三、关键字相关题目

1.关于下面的程序,说法正确的是()

public class Demo {
    static String x = "1";
    static int y = 1;
    public static void main (String[] args) { 
        static int z= 2;
        System.out.println(x+y+z);
    }       
}

A. 3
B. 112
C. 13
D. 程序有编译错误

答案:D
笔记:
static变量是类变量,不能定义在方法中。

2.true、false、null、sizeof、goto、synchronized 哪些是Java关键字()
A. true
B. false
C. null
D. sizeof
E. goto
F. synchronized

答案:EF
笔记:
goto和const既是保留字也是关键字。除了这两个之外,关键字和保留字是严格区分开的。
null、true、false是保留字。所谓保留字,就是现有java版本尚未使用,但以后版本可能会作为关键字使用。
关键字有50个,保留字有14个。
而sizeof是C语言中的关键字,在java中并不是。

3.以下关于final关键字说法错误的是()
A final是java中的修饰符,可以修饰类、接口、抽象类、方法和属性
B final修饰的类肯定不能被继承
C final修饰的方法不能被重载
D final修饰的变量不允许被再次赋值

答案:C
笔记:
final修饰类表示类不可被继承,修饰方法表示方法不可被重写,修饰常量表示引用不可改。

4.有关下述Java代码描述正确的选项是()

public class TestClass {
   private static void testMethod(){
        System.out.println("testMethod");
   }
   public static void main(String[] args) {
        ((TestClass)null).testMethod();
   }
}

A. 编译不通过
B. 编译通过,运行异常,报NullPointerException
C. 编译通过,运行异常,报IllegalArgumentException
D. 编译通过,运行异常,报NoSuchMethodException
E. 运行正常,输出testMethod

答案:E
笔记:
将null强制转换成TestClss类型,因此((TestClass)null)这个整体也就表示一个TestClass类型的对象了。
static成员属于类成员(成员包括属性和方法),static方法,即类方法,可以直接通过”类名.方法名”进行访问。但static方法也可以通过”对象.方法名”进行访问,也就是说我们可以通过类的实例去调用,但其实质是转化成类来调用。

5.在使用super和this关键字时,以下描述正确的是()
A 在子类构造方法中使用super()显示调用父类的构造方法,super()必须写在子类构造方法的第一行,否则编译不通过
B super()和this()不一定要放在构造方法内第一行
C this()和super()可以同时出现在一个构造函数中
D this()和super()可以在static环境中使用,包括static方法和static语句块

答案:A
笔记:
this()和super()都必须写在第一行,因此不能同时出现在同一个构造方法中。
super()调用的是父类的构造器,this()调用的是同一类中重载的构造器。
static方法中无法使用this关键字。且this()和super()只能出现在构造方法中。

6.关键字super的作用是()
A 用来访问父类被隐藏的非私有成员变量
B 用来调用父类中被重写的方法
C 用来调用父类的构造函数
D 以上都是

答案:D
笔记:
super代表父类对应的对象,所以用super访问在子类中无法直接使用的父类成员和方法、以及构造方法。

四、多态

1.对于如下代码段,可以放入到横线位置,使程序正确编译运行,而且不产生错误的选项是( )

class A{
    public A foo(){
        return this;
    }
}
class B extends A{
    public A foo(){
        return this;
    }
}
class C extends B{
    _______
}

A. public void foo(){}
B. public int foo(){return 1;}
C. public A foo(B b){return b;}
D. public A foo(){return A;}

答案:C
笔记:
A和B,返回值类型类B的foo方法不一样,因此,不可能是方法重写,因此,只有可能是方法重载,但是方法重载又要求方法形参列表不同,因此,也不可能是方法重载。因此,无法通过编译。
继续分析C,由于C选项的foo方法形参列表与类B的形参列表不同,因此,不可能是方法重写,只可能是方法重载,而C选项的foo方法满足方法重载的所有要求(方法名相同、形参列表不同),因此C选项正确。
D,返回A,编译不通过。

2.(多选题)类Parent和Child定义如下,对于如下代码段,可以放入到横线位置,使程序正确编译运行,而且不产生错误的选项是( )

class Parent{
    public float aFun(float a, float b){return a+b;}
}
class Child extends Parent{
    _______
}

A. float aFun(float a, float b){return a+b;}
B. public int aFun(int a, int b){return a+b;}
C. public float aFun(float a, float b){return a+b;}
D. private int aFun(int a, int b){return a+b;}

答案:BCD
笔记:
对于BD选项,方法形参列表不同,因此不可能是方法重写,只可能是方法重载,方法重载的条件是方法名相同,形参列表不同,因此,满足条件。(方法重载无关返回值类型和方法访问权限)。
对于AC选项,形参列表相同,因此不可能是方法重载,因此只可能是方法重写。方法重写条件:两同两小一大,C均满足,A不满足”一大”。
具体分析A,普通类方法的默认访问权限是包内访问权限,也就是default,但不能显式的写default,由于父类的aFun方法的访问权限是public,对于方法重写,子类重写的方法的访问权限不应小于父类方法的访问权限,故A错。

3.以下方法,哪个不是对add方法的重载()

public class Test{
    public void add( int x,int y,int z){}
}

A. public int add(int x,int y,float z){return 0;}
B. public int add(int x,int y,int z){return 0;}
C. public void add(int x,int y){}
D. 以上都不是

答案:B
笔记:
重载规则:方法名相同,形参列表不同。B的话形参列表和方法名都与Test类中的add方法相同。返回值类型、方法访问权限无关重载。

4.下列哪些针对代码运行结果的描述是正确的?

public class Car extends Vehicle
{
    public static void main (String[] args)
    {
        new Car().run();
    }
    private final void run()
    {
        System.out.println ("Car");
    }
}
class Vehicle
{
    private final void run()
    {
        System.out.println("Vehicle");
    }
}

A. Car
B. Vehicle
C. Compiler error
D. Exception thrown at runtime

答案:A
笔记:
final修饰方法表方法不可重写。而private修饰方法,表示该方法是私有方法,即子类不可见。因此在这道题中,类Car中的run方法和父类Vehicle中的run方法没有任何关系。也就是说不存在方法重写与重载。因此,当执行new Car()时,执行的是子类的run方法。并且没有编译错误,运行时也不会出现异常。

5.下列程序执行后结果为( )

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 Result=150 Result=150
B Result=100 Result=100
C Result=100 Result=150
D Result=150 Result=100

答案:A
笔记:
对于方法,非静态:编译看左,运行看右 静态成员变量:都看左。
1.成员变量:编译和运行都参考左边。
2.成员函数(非静态):编译看左边,运行看右边
3.静态函数:编译和运行都看左边。

6.这个程序的输出结果是()

package Wangyi;
class Base
{
    public void method()
    {
        System.out.println("Base");
    } 
}
class Son extends Base
{
    public void method()
    {
        System.out.println("Son");
    }

    public void methodB()
    {
        System.out.println("SonB");
    }
}
public class Test01
{
    public static void main(String[] args)
    {
        Base base = new Son();
        base.method();
        base.methodB();
    }
}

A Base SonB
B Son SonB
C Base Son SonB
D 编译不通过

答案:D
笔记:
Base base = new Son();
这句new 了一个派生类,赋值给基类,所以下面的操作编译器认为base对象就是Base类型的
Base类中不存在methodB()方法,所以编译不通过。
对于成员函数:编译看左边,运行看右边。意思编译时候,看左边有没有该方法,运行的时候结果看 new 的对象是谁,就调用的谁。
1.成员变量:编译和运行都参考左边。
2.成员函数(非静态):编译看左边,运行看右边
3.静态函数:编译和运行都看左边。

7.在java的多态调用中,new的是哪一个类就是调用的哪个类的方法()
A 对
B 错

答案:B
笔记:
1.成员变量:编译和运行都参考左边。
2.成员函数(非静态):编译看左边,运行看右边
3.静态函数:编译和运行都看左边。
举例如:

public class Demo{
    public static void main(String[] args){
        P p = new M();
        p.f();
    }
}
class P{
    public static void f(){
        System.out.println("parent");
    }
}
class M extends P{
}

尽管new的是类M,但调用的是父类P的方法,除非子类重写了该方法。

8.对于如下代码段

class A{
    public A foo(){return this;}
}
class B extends A{
    public A foo(){
        return this;
    }
}
class C extends B
{
    _______
}

可以放入到横线位置,使程序正确编译运行,而且不产生错误的选项是( )
A public void foo(){}
B public int foo(){return 1;}
C public A foo(B b){return b;}
D public A foo(){return A;}

答案:C
笔记:
很明显考的是重载和重写,对于AB,返回值类型与父类方法的返回值类型不同,因此肯定不是方法重写,因此只可能是方法重载,但重载又要求形参列表必须不同,因此也不可能是重载,因此AB编译不通过。对于D,返回A,很明显是有问题的。对于C,形参列表不同,因此是方法重载。

总结:方法重写Override与方法重载Overload

方法重写:
子类方法重写父类方法遵循“两同两小一大”的规则:
“两同”即方法名相同,形参列表相同
“两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等(这是因为返回值类型更大或者更小,是对于同一类型而言的。也就是说,返回值的类型需要有继承关系才去考虑大小这个概念。类型不同,肯定不是方法重写)
“一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。
方法重载:
重载是一个类中出现多个同名的方法。因此,我们考虑重载,是在类中有同名方法的前提下。
方法名相同、方法形参列表不同。

五、修饰符问题

1.以下声明合法的是()
A. default String s;
B. public final static native int w();
C. abstract double d;
D. abstract final double hyperboilcCosine;(hyperboilcCosine译为双曲余弦函数)

答案:B
笔记:
在类中不能显式的用default修饰变量和方法,但如果没有写访问权限控制符,默认是包权限。因此A错。abstract表抽象,不能修饰变量,因此C错。abstract和final不能同时方法或类,因此D错。static表静态属性,final修饰方法表方法不可重写,B选项声明合法。
补充:
普通类中方法和属性的默认访问权限是default,但不能显示的写default。
抽象类的方法和属性的默认访问权限,在jdk1.7中是protected,在jdk1.8中是default。jdk1.8中这样做是为了让抽象类与其实现类必须在同一个包中。
接口的方法和属性的默认访问权限,是public。
普通类与抽象类中的方法和属性,不能使用default修饰。接口中的方法,可以用default修饰,表示默认方法,且该方法必须有实现体。

2.下面哪一个是正确的输出结果()

class Foo {
    final int i;
    int j;
    public void doSomething() {
        System.out.println(++j + i);
    }
}

A 0
B 1
C 2
D 不能执行,因为编译有错

答案:D
笔记:
final修饰的成员在使用前必须初始化。
再看下面的例子:

public static void main(String[] args){
    for(int i=0;i<10;i++){
        final int a = i;
        System.out.print(a+" ");
    }
}

我们知道被final修饰的变量只能赋值一次,那么上面的例子会出现编译问题吗。不会,因为遍历a的作用于只在花括号之间,每轮循环结束,变量a就被回收了。也就是说每轮循环的变量a都是不一样的。

六、基本数据类型的自动转换与强制转换

1.(多选题)Java类Demo中存在方法func1、func2、func3和func4,请问该方法中,哪些是不合法的定义( )

public class Demo{
    float func1(){
        int i=1;
        return;
    }
    float func2(){
        short i=2;
        return i;
    }
    float func3(){
        long i=3;
        return i;
    }
    float func4(){
        double i=4;
        return i;
    }
}

A. func1
B. func2
C. func3
D. func4

答案:AD
笔记:
数据类型的转换,分为自动转换和强制转换。
数据类型从大到小需要强制转换,必须在代码中声明,由小到大不需要,会自动转换。
不同类型数据间的优先关系如下:byte、short、char < int < long

byte b1=1,b2=2,b3,b6,b8;
final byte b4=4,b5=6,b7;
b3=(b1+b2);  /*语句1*/
b6=b4+b5;    /*语句2*/
b8=(b1+b4);  /*语句3*/
b7=(b2+b5);  /*语句4*/
System.out.println(b3+b6);

A. 语句1
B. 语句2
C. 语句3
D. 语句4

答案:ACD
笔记:
byte、short、char类型的任意两个数据想要进行运算操作,都会先转换成int类型,再进行运算操作。final修饰的变量例外。
对于A,当执行b1+b2,b1和b2会先转换成int类型,再进行加运算,再把结果赋给byte类型的b3,就会出现数据类型由大到小,从而出现编译错误。故A错。
对于B,当执行b4+b5,由于b4和b5都是final类型的,因此不会自动转换成int类型,所以和的类型视左边变量类型而定,故B对。
对于C,当执行b1+b4,虽然b4是final类型,不会自动转换成int类型,但是b1会转化成int类型,故和的类型为int类型,因此由于缺少强制转换,故C错。
对于D,同C一个道理,故D错。

3.下面有关java基本类型的默认值和取值范围,说法错误的是()
A 字节型的类型默认值是0,取值范围是-2^7—2^7-1
B boolean类型默认值是false,取值范围是true\false
C 字符型类型默认是0,取值范围是-2^15 —2^15-1
D long类型默认是0,取值范围是-2^63—2^63-1

答案:B
笔记:

七、原码反码补码

1.经过强制类型转换以后,变量a,b的值分别为多少()

short a = 128;
byte b = (byte)a;

A. 128 127
B. 128 -128
C. 128 128
D. 编译错误

答案:B
笔记:
一个short变量占2个字节,即16位,一个byte变量占1个字节,即8位。
a的二进制表示为:00000000 10000000,把a强制转换成byte类型再赋给b,因此高8位被截掉,剩下低8位,故b的二进制表示为:10000000。原码10000000表示的是-0,计算机中使用的是补码,原码10000000对应的补码在计算机中表示的是-128。

2.变量a是一个64位有符号的整数,初始值用16进制表示为:0x 7FFFFFFF FFFFFFFF,变量b是一个64位有符号的整数,初始值用16进制表示为:0x 80000000 00000000,则a+b的结果用10进制表示为()
A. 1
B. -1
C. 2^63+2^62+…+2^2+2^1+2^0
D. -(2^63+2^62+…+2^2+2^1+2^0)

答案:B
笔记:
a+b,得到的结果的16进制表示为0x FFFFFFFF FFFFFFFF,这是计算机中表示的方式,即反码的表示,负数的反码等于原码(除符号位外的其他位)取反+1,由此可得原码为0x 10000000 00000001,其10进制表示为-1,故答案选B。

3.变量a是一个64位有符号的整数,初始值用16进制表示为:0Xf000000000000000; 变量b是一个64位有符号的整数,初始值用16进制表示为:0x7FFFFFFFFFFFFFFF。 则a-b的结果用10进制表示为多少?()
A 1
B -(2^62+2^61+2^60+1)
C 2^62+2^61+2^60+1
D 2^59+(2^55+2^54+…+2^2+2^1+2^0)

答案:C
笔记:
0Xf000000000000000补码为1111000000000000000000000000000000000000000000000000000000000000
0x7FFFFFFFFFFFFFFF补码为0111111111111111111111111111111111111111111111111111111111111111
a-b=a+(-b)=
1111000000000000000000000000000000000000000000000000000000000000+
1000000000000000000000000000000000000000000000000000000000000001=
10111000000000000000000000000000000000000000000000000000000000001(高位溢出舍去)
则结果为
0111000000000000000000000000000000000000000000000000000000000001=
2^62+2^61+2^60+1
其中利用到了~n=-n-1这个公式。

4.检查程序,是否存在问题,如果存在指出问题所在,如果不存在,说明输出结果()

int i = 5;
int j = 10;
System.out.println(i+~j);

A. 15
B. -5
C. -6
D. 编译错误

答案:C
笔记:
~是位运算符号,表示取反。有个公式,-n-1=~n。因此i+~j=i+(-j-1)=5-10-1=-6。
或者这么做:
先计算出j在计算机中的表示方式,即j的补码,从而算出j的补码取反,再求5的补码,再相加(在计算机中都是以补码的进行操作),再转换成原码,从而转换成10进制表示。
10是正数,因此反码等于补码为00001010,取反得到11110101,5的补码为00000101,
01110101+
10000101=
11111010,这是反码表示,其对应的原码为10000110,转换成10进制,即-6。
ps:负数的补码时:符号位位1,其余各位求反,末位加1。

八、编码转码

1.下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换()

byte[] src,dst;

A dst=String.fromBytes(src,”GBK”).getBytes(“UTF-8”)
B dst=new String(src,”GBK”).getBytes(“UTF-8”)
C dst=new String(“GBK”,src).getBytes()
D dst=String.encode(String.decode(src,”GBK”)),”UTF-8” )

答案:B
笔记:
先用new String(src,”GBK”)解码得到字符串,再用getBytes(“UTF-8”)得到UTF8编码字节数组。
String(byte[] b,Charset charset):通过使用指定的charset解码指定的byte数组,构造一个新的String。
还有一种情形是new String(str.getBytes(“gbk”),”utf-8”);先通过getBytes方法得到gbk编码字节数组,再通过new String(bytes,”utf-8”)解码得到字符串。

九、import相关问题

1.有一个源代码,只包含import java.util.*,这是一个import语句,下面叙述正确的是()
A. 只能写在源代码的第一句
B. 可以访问java/util目录下及其子目录下的所有类
C. 能访问java/util目录下的所有类,不能访问java/util子目录下的所有类
D. 编译错误

答案:C
笔记:
导入包,只能访问该包目录下的类,而不包括其子目录中的类。
package语句必须写在第一行(忽略注释行),import语句写在package语句之后,类的定义之前。

十、陷阱之有参构造函数

1.以下输出的结果为()

class Base{
    public Base(String s){
        System.out.println("B");
    }
}
public class X extends Base{
    public X(String s){
        System.out.println("D");
    }
    public static void main(String args[]){
        new X("C");
    }
}

A. BD
B. DB
C. C
D. 编译错误

答案:D
笔记:
当父类只有有参构造函数而没定义无参构造函数的时候,要特别小心。子类必须显式调用父类的构造方法,否则,编译将不能通过。如果父类中定义了无参构造函数,子类会默认调用父类的无参构造函数。

十一、JVM相关问题

1.对于JVM内存配置参数:
-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRadio=3,其最小内存值和Survivor区总大小分别是()
A. 5120m,1024m
B. 5120m,2048m
C. 10240m,1024m
D. 10240m,2048m

答案:D
笔记:
-Xms:初始堆大小
-Xmx:最大堆大小
-Xmn:年轻代大小
-Xss:每个线程的堆栈大小
-XXSurvivorRadio:年轻代中Eden区与Survivor区的大小比值。
-XX:NewRatio:设置年轻代与年老代的比值
Survivor区有两个(又称为from区和to区),因此一个Survivor区占总的年轻代内存的五分之一。

2.下列哪项不属于jdk1.6垃圾收集器()
A. Serial收集器
B. parNew收集器
C. CMS收集器
D. G1收集器

答案:D
笔记:
这里写图片描述

3.(多选题)以下哪些jvm的垃圾回收方式采用的是复制算法回收 1/1
A. 新生代串行收集器
B. 老年代串行收集器
C. 新生代并行回收收集器
D. 老年代并行回收收集器
E. cms收集器

答案:AC
笔记:
新生代采用复制算法,老年代采用标记-整理或标记-清除算法。
MS表示 mark sweep,即标记-清除,
MC表示 mark compression,即标记-压缩,
因此,CMS表示Concurrent Mark Sweep,即多线程标记-清除。
G1收集器比较特殊,整体上是基于标记-整理,局部采用复制。

4.下列Java代码中的变量a、b、c分别在内存的__存储区存放。

class A {
    private String a = “aa”;
    public boolean methodB() {
        String b = “bb”;
        final String c = “cc”;
    }
}

A 堆区、堆区、堆区
B 堆区、栈区、堆区
C 堆区、栈区、栈区
D 堆区、堆区、栈区
E 静态区、栈区、堆区
F 静态区、栈区、栈区

答案:C
笔记:
a是类中的成员变量的引用,存放在堆中,b和c都是方法中的局部变量的引用,存在于栈中。

5.下面输出顺序顺序的是()

class B extends Object{
    static{
        System.out.println("Load B");
    }
    public B(){
        System.out.println("Create B");
    }
}
class A extends B{
    static{
        System.out.println("Load A");
    }
    public A(){
        System.out.println("Create A");
    }
}

public class Testclass{
    public static void main(String[] args){
        new A();
    }
}

A. Load B ->Create B->Load A -> Create A
B. Load B -> Load A ->Create B ->Create A
C. Load B -> Create B-> Create A -> Load A
D. Create B ->Create A ->Load B ->Load A

答案:B
笔记:
类的加载顺序:
1. 初始化父类中的静态成员变量和静态代码块 ;
2. 初始化子类中的静态成员变量和静态代码块 ;
3. 初始化父类的普通成员变量和代码块,再执行父类的构造方法;
4. 初始化子类的普通成员变量和代码块,再执行子类的构造方法;

6.下面对JVM叙述不正确的是:()
A JVM的全称是Java Virtual Machine
B JVM是一种计算机硬件技术,它是Java程序的运行平台
C JVM是在计算机硬件系统上用软件实现的一台假想机
D Java程序在执行时.JVM把Java字节码解释成机器码

答案:B
笔记:
JVM即Java Virtual Machine,即Java虚拟机,是在现有的平台如windows、linux上运行的一个软件,虚拟出一台接口统一的计算机,实现java语言的跨平台特性。
Java虚拟机是一颗可执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。Java被设计称允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变成可能,因为它知道底层硬件平台的指令长度和其他特性。

7.下面有关JVM内存,说法错误的是?()
A 程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的
B 虚拟机栈描述的是Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的
C 方法区用于存储JVM加载的类信息、常量、静态变量、以及编译器编译后的代码等数据,是线程隔离的
D 原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的

答案:C
笔记:
方法区在JVM中也是一个非常重要的区域,它与堆一样,是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。

8.以下代码的输出结果是()

public class B {
    public static B t1 = new B();
    public static B t2 = new B();
    {
        System.out.println("构造块");
    }
    static {
        System.out.println("静态块");
    }
    public static void main(String[] args) {
        B t = new B();
    }
}

A 静态块 构造块 构造块 构造块
B 构造块 静态块 构造块 构造块
C 构造块 构造块 静态块 构造块
D 构造块 构造块 构造块 静态块

答案:C
笔记:
开始时JVM加载B.class,先执行静态成员的声明,再执行main方法。另外,每一次实例化对象时,先执行构造块,再执行构造函数块。

9.When is the text “Hi there”displayed?()

public class StaticTest
{
    static
    {
        System.out.println(“Hi there”);
    }

    public void print()
    {
        System.out.println(“Hello”);
    }

    public static void main(String args[])
    {
        StaticTest st1 = new StaticTest();
        st1.print();
        StaticTest st2 = new StaticTest();
        st2.print();
    }
}

A Never.
B Each time a new object of type StaticTest is created.
C Once when the class is loaded into the Java virtual machine.
D Only when the main() method is executed.

答案:C
笔记:
被static修饰的属性或方法,仅在类第一次加载进JVM时执行。

10.What will be printed when you execute the following code?

class C {
    C() {
        System.out.print("C");
    }
}

class A {
    C c = new C();

    A() {
        this("A");
        System.out.print("A");
    }

    A(String s) {
        System.out.print(s);
    }
}

class Test extends A {
    Test() {
        super("B");
        System.out.print("B");
    }

    public static void main(String[] args) {
        new Test();
    }
}

A BB
B CBB
C BAB
D None of the above

答案:B
笔记:
1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
3.其次,初始化父类的普通成员变量和代码块,再执行父类的构造方法;
4.最后,初始化子类的普通成员变量和代码块,再执行子类的构造方法;
其中,super(“B”); 表示调用父类的构造方法,不调用父类的无参构造函数。

11.下面有关java classloader说法正确的是()?
A ClassLoader就是用来动态加载class文件到内存当中用的
B JVM在判定两个class是否相同时,只用判断类名相同即可,和类加载器无关
C ClassLoader使用的是双亲委托模型来搜索类的
D Java默认提供的三个ClassLoader是Boostrap ClassLoader,Extension ClassLoader,Application ClassLoader

答案:ACD
笔记:
from牛客网用户“早起吃虫啦”:

JDK中提供了三个ClassLoader,根据层级从高到低为:
Bootstrap ClassLoader,主要加载JVM自身工作需要的类。
Extension ClassLoader,主要加载%JAVA_HOME%\lib\ext目录下的库类。
Application ClassLoader,主要加载Classpath指定的库类,一般情况下这是程序中的默认类加载器,也是ClassLoader.getSystemClassLoader() 的返回值。(这里的Classpath默认指的是环境变量中配置的Classpath,但是可以在执行Java命令的时候使用-cp 参数来修改当前程序使用的Classpath)
JVM加载类的实现方式,我们称为 双亲委托模型:
如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是把这个请求委托给自己的父加载器,每一层的类加载器都是如此,因此所有的类加载请求最终都应该传送到顶层的Bootstrap ClassLoader中,只有当父加载器反馈自己无法完成加载请求时,子加载器才会尝试自己加载。
双亲委托模型的重要用途是为了解决类载入过程中的安全性问题。
假设有一个开发者自己编写了一个名为Java.lang.Object的类,想借此欺骗JVM。现在他要使用自定义ClassLoader来加载自己编写的java.lang.Object类。然而幸运的是,双亲委托模型不会让他成功。因为JVM会优先在Bootstrap ClassLoader的路径下找到java.lang.Object类,并载入它。

from牛客网用户“大萝卜小萝卜”:

  1. 什么是类加载器?
    把类加载的过程放到Java虚拟机外部去实现,让应用程序决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。
  2. 有哪些类加载器,分别加载哪些类
    类加载器按照层次,从顶层到底层,分为以下三种:
    (1)启动类加载器 : 它用来加载 Java 的核心库,比如String、System这些类
    (2)扩展类加载器 : 它用来加载 Java 的扩展库。
    (3) 应用程序类加载器 : 负责加载用户类路径上所指定的类库,一般来说,Java 应用的类都是由它来完成加载的。
  3. 双亲委派模型
    我们应用程序都是由以上三种类加载器互相配合进行加载的,还可以加入自己定义的类加载器。称为 类加载器的双亲委派模型 ,这里类加载器之间的父子关系一般不会以继承的关系来实现,而是都使用 组合关系 来复用父加载器的。
  4. 双亲委托模型的工作原理
    是当一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法加载这个加载请求的时候,子加载器才会尝试自己去加载。
  5. 使用双亲委派模型好处?(原因)
    第一:可以避免重复加载,当父亲已经加载了该类的时候,子类不需要再次加载。
    第二:考虑到安全因素,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的类装载器。

十二、网络编程

1.关于Socket通信编程,以下描述错误的是:( )
A 服务器端通过new ServerSocket()创建TCP连接对象
B 服务器端通过TCP连接对象调用accept()方法创建通信的Socket对象
C 客户端通过new Socket()方法创建通信的Socket对象
D 客户端通过new ServerSocket()创建TCP连接对象

答案:D
笔记:
服务器端通过new ServerSocket()创建TCP连接对象,通过TCP连接对象调用accept()方法创建通信的Socket对象。
客户端通过new Socket()方法创建通信的Socket对象

十三、泛型

1.以下说法错误的是()
A 虚拟机中没有泛型,只有普通类和普通方法
B 所有泛型类的类型参数在编译时都会被擦除
C 创建泛型对象时请指明类型,让编译器尽早的做参数检查
D 泛型的类型擦除机制意味着不能在运行时动态获取List中T的实际类型

答案:D
笔记:
虚拟机中没有泛型,只有普通类和普通方法;所有泛型类的类型参数在编译时都会被擦除;创建泛型对象的时候,一定要指出类型变量T的具体类型。争取让编译器检查出错误,而不是留给JVM运行的时候抛出类不匹配的异常。
通过反射可以获取获取List中T的实际类型。

2.(多选题)Which four statements are true ?()
class A {}
class B extends A {}
class C extends A {}
class D extends B {}
A. The type List<A>is assignable to List.
B. The type List<B>is assignable to List<A>.
C. The type List<Object>is assignable to List<?>.
D. The type List<D>is assignable to List<?extends B>.
E. The type List<?extends A>is assignable to List<A>.
F. The type List<Object>is assignable to any List reference.
G. The type List<?extends B>is assignable to List<?extends A>.

答案:ACDG
笔记:
from牛客网的用户:晓宇大美女~
1. 只看尖括号里边的,明确点和范围两个概念
2. 如果尖括号里的是一个类,那么尖括号里的就是一个点,比如List<A>List<B>List<Object>
3. 如果尖括号里面带有问号,那么代表一个范围,<? extends A> 代表小于等于A的范围,<? super A>代表大于等于A的范围,<?>代表全部范围
4. 尖括号里的所有点之间互相赋值都是错,除非是俩相同的点
5. 尖括号小范围赋值给大范围,对,大范围赋值给小范围,错。如果某点包含在某个范围里,那么可以赋值,否则,不能赋值
6. List<?>List 是相等的,都代表最大范围
7. List既是点也是范围,当表示范围时,表示最大范围

十四、继承

1.以下代码执行的结果显示是多少()

public class Demo {
    class Super {
        int flag = 1;
        Super() {
            test();
        }
        void test() {
            System.out.println("Super.test() flag=" + flag);
        }
    }
    class Sub extends Super {
        Sub(int i) {
            flag = i;
            System.out.println("Sub.Sub()flag=" + flag);
        }
        void test() {
            System.out.println("Sub.test()flag=" + flag);
        }
    }
    public static void main(String[] args) {
        new Demo().new Sub(5);
    }
}

A. Sub.test() flag=1 Sub.Sub() flag=5
B. Sub.Sub() flag=5 Sub.test() flag=5
C. Sub.test() flag=0 Sub.Sub() flag=5
D. Super.test() flag=1 Sub.Sub() flag=5

答案:A
笔记:
当实例化Sub类的之前,会先实例化其父类,因此父类先初始化执行int flag=1,然后执行父类的构造方法,父类的构造方法中执行了test方法,而由于子类重写了父类的test方法,因此父类中调用了是子类的test方法,因此当执行父类的构造方法,输出的是Sub.test() flag=1,执行完父类的构造方法后,继续执行子类的构造方法,输出结果:Sub.Sub() flag=5。

2.下面代码的输出是什么()

public class Base{
    private String baseName = "base";
    public Base(){
        callName();
    }
    public void callName(){
        System. out. println(baseName);
    }
    static class Sub extends Base{
        private String baseName = "sub";
        public void callName(){
            System. out. println (baseName) ;
        }
    }
    public static void main(String[] args){
        Base b = new Sub();
    }
}

A. null
B. sub
C. base

答案:A
笔记:
在main函数中实例化Sub,会先实例化其父类Base,因此先实例化Base的私有属性baseName=”base”,然后执行父类的构造方法,在构造方法中调用了callName方法,由于子类重写了该方法,于是,父类调用的是子类的callName方法,重点是!子类的callName方法中调用的baseName是子类的私有属性(子类无法访问父类的私有属性),但此时子类由于还没有实例化baseName属性,因此输出为null。
为什么会出现子类属性还没有实例化的情况呢,这是因为父类的属性实例化以及父类执行构造方法的顺序先于子类。具体顺序可以看下面的继承模块的总结。

3.下列对继承的说法,正确的是( )
A. 子类能继承父类的所有成员
B. 子类继承父类的非私有方法和状态
C. 子类只能继承父类的public方法和状态
D. 子类只能继承父类的方法

答案:A
笔记:
摘自牛客网用户——柠檬。2020:
从继承的概念来说: private和final不被继承。Java官方文档上是这么说的。
从内存的角度来说: 父类的一切都被继承(从父类构造方法被调用就知道了,因为new一个对象,就会调用构造方法,子类被new的时候就会调用父类的构造方法,所以从内存的角度来说,子类拥有一个完整的父类)。子类对象所引用的内存有父类变量的一份拷贝.
所以说,子类是继承了父类的所有成员(成员指的是字段、方法、嵌套类)。但是对于私有成员,虽然继承了,但是无法访问。
另外!!很重要的一点是,构造函数不是成员!!因此,子类并没有继承父类的构造方法,构造方法不被子类继承,但是子类可以调用父类的构造方法。

4.(多选题)java中关于继承的描述正确的是()
A. 一个子类只能继承一个父类
B. 子类可以继承父类的构造方法
C. 继承具有传递性
D. 父类一般具有通用性,子类更具体

答案:CD
笔记:
子类继承父类的所有成员(成员包括属性和方法以及嵌套类),但能继承不代表有权限访问。另外,构造方法不属于成员之一,即子类没有继承父类的构造方法,也就是说子类只能调用父类的构造方法,但没有继承父类的构造方法。

总结-在继承中代码的执行顺序

在继承中代码的执行顺序为:
1.父类静态对象,父类静态代码块;
2.子类静态对象,子类静态代码块;
3.父类非静态对象,父类非静态代码块;
4.父类构造函数;
5.子类非静态对象,子类非静态代码块;
6.子类构造函数;

十五、内部类

1.下列说法正确的是()
A. 对于局部内部类,只有在方法的局部变量被标记为final或局部变量是effctively final的,内部类才能使用它们
B. 成员内部类位于外部类内部,可以直接调用外部类的所有方法(静态方法和非静态方法)
C. 由于匿名内部类只能用在方法内部,所以匿名内部类的用法与局部内部类是一致的
D. 静态内部类可以直接访问外部类的成员变量

答案:A
笔记:
局部内部类,可以参考局部变量,指的是定义在方法中的类。
成员内部类特指非静态的,静态内部类不能称之为成员,故B错。
匿名内部类并不只能用于方法内部,匿名内部类的特点是只能使用一次。故C错。
静态内部类不能直接访问外部类的非静态成员,但是可以通过new 外部类().成员的方式访问,故A错。

2.Given the following code:

class Enclosingone
{
    public class InsideOne {}

}
public class inertest
{
    public static void main(string[]args)
    {
        EnclosingOne eo = new EnclosingOne();
        //insert code here
    }

}

Which statement at line 11 constructs an instance of the inner class?
A. InsideOne ei=eo.new InsideOne();
B. eo.InsideOne ei=eo.new InsideOne();
C. InsideOne ei=EnclosingOne.new InsideOne();
D. EnclosingOne.InsideOne ei=eo.new InsideOne();

答案:D
笔记:
如果内部类是静态内部类,那么正确的答案写法就是:
EncolsingOne.InsideOne obj = new EnclosingOne.InsideOne();

4.下列外部类定义中,不正确的是:( )
A class x { …. }
B class x extends y { …. }
C static class x implements y1,y2 { …. }
D public class x extends Applet { …. }

答案:C
笔记:
外部类的修饰符只能是public,abstract,final。
当一个类是内部类时可以用public,protected和private修饰,或者是默认的包访问权限。

5.关于访问权限说法正确的是( )
A 类定义前面可以修饰public,protected和private
B 内部类前面可以修饰public,protected和private
C 局部内部类前面可以修饰public,protected和private
D 以上说法都不正确
答案:B

总结:内部类

关于内部类的有一篇非常棒的文章:Java内部类详解
感觉如果能把这篇文章弄明白,那内部类就没什么问题了。

下面对静态内部类和成员内部类做下简单的笔记:
内部类具体分为四种:
成员内部类、静态内部类、匿名内部类、局部内部类。
对于成员内部类:
成员内部类是外部类的成员之一,既然是成员,自然可以使用各种访问权限修饰符。
此外成员内部类可以无条件的访问外部类的所有属性和成员,包括用private修饰的成员。但要注意的是,如果成员内部类拥有和外部类同名的成员变量或方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员,如果要访问外部类的成员,需要通过如下方式:

外部类.this.成员属性;
外部类.this.成员方法;

而外部类要想访问成员内部类的成员,则必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

内部类().内部类成员;

实例化成员内部类的写法:

Outter outter = new Outter();//要实例化成员内部类,前提必须是存在一个外部类对象,因为成员内部类是依附于外部类存在的。
Outter.Inner inner = outter.new Inner();

而静态内部类的实例化的写法是:

Outter.Inner inner = new Outter.Inner();

十六、异常

1.下列程序的运行结果()

public void getCustomerInfo() {
        try {
            // do something that may cause an Exception
        } catch (java.io.FileNotFoundException ex) {
            System.out.print("FileNotFoundException!");
        } catch (java.io.IOException ex) {
            System.out.print("IOException!");
        } catch (java.lang.Exception ex) {
            System.out.print("Exception!");
        }
    }

A. IOException!
B. IOException!Exception!
C. FileNotFoundException!IOException!
D. FileNotFoundException!IOException!Exception!

答案:A
笔记:
一个try块可能有多个catch块,且catch块异常类型必须小的在前大的在后,多个catch块中有且只能执行一个catch块。
另外,try…catch…finally结构中,可以是try.catch,也可以是try…finally,还可以是try…catch…finally。只能是 这三种中的一种。

2.下面函数将返回()

public static int func (){
    try{
        return 1;
    }catch (Exception e){
        return 2;
    }finally{
        return 3;
    }
}

A. 1
B. 2
C. 3
D. 编译错误

答案:A
笔记:
如果try、catch、finally中均有return语句,那么最终生效的将是finally的return语句。除非遇到System.exit()语句。

3.请问所有的异常类皆直接继承于哪一个类?()
A java.applet.Applet
B java.lang.Throwable
C java.lang.Exception
D java.lang.Error

答案:C
笔记:

4.下面代码的输出结果是什么?

public class ZeroTest {
    public static void main(String[] args) {
        try {
            int i = 100 / 0;
            System.out.print(i);
        } catch (Exception e) {
            System.out.print(1);
            throw new RuntimeException();
        } finally {
            System.out.print(2);
        }
        System.out.print(3);
    }
}

A 3
B 123
C 1
D 12

答案:D
笔记:
在catch中又抛出了异常,这时除了执行finally中的代码,往下的代码都不会执行了。

十七、Object类相关题目

1.下面不属于Object类中方法的是()
A. hashCode()
B. finally()
C. wait()
D. toString()

答案:B
笔记:Object类的方法共九个:
1. equals方法
2. hashCode方法
3. toString方法
4. getClass方法
5. notify方法
6. notifyAll方法
7. 8. 9. wait方法(共有三个)

2.下面有关java object默认的基本方法,说法错误的是?()
A equals(Object obj) 指示某个其他对象是否与此对象“相等”
B copy() 创建并返回此对象的一个副本
C wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
D toString() 返回该对象的字符串表示

答案:B
笔记:
Object类中没有copy方法,只有clone方法,clone方法才是创建并返回此对象的一个副本。

3.有这么一段程序:

public class Test{ 
    public String name="abc"; 
    public static void main(String[] args){ 
        Test test=new Test(); 
        Test testB=new Test(); 
        System.out.println(test.equals(testB)+","+test.name.equals(testB.name)); 
    } 
}

请问以上程序执行的结果是()
A true,true
B true,false
C false,true
D false,false

答案:C
笔记:
这道题考的是equals方法,equals方法继承自Object类。所有的类都直接或者间接继承自Object类。Test类没有重写equals方法,因此该实现是Object类中的实现,即比较两个对象的地址是否相等。因此test.equals(testB)为false。
我们要注意,如果我们自定义了一个类,又需要将它用来比较,就必须得重写equals方法,即定义一个比较的规则。

十八、基本数据类型

1.下面为true的是()

Integer i = 42;
Long l = 42l;
Double d = 42.0;
下面为true的是 1/1
A (i == l)
B (i == d)
C (l == d)
D i.equals(d)
E d.equals(l)
F i.equals(l)
G l.equals(42L)

答案:G
笔记:
对于“==”,
如果两边是对象,那么比较的是两对象必须为同一种类型的变量,否则编译不通过。如果是同一种类型的变量,则判断地址是否相等。因此,ABC错。
如果一边是基本类型变量,一遍是包装类对象,那么会自动拆箱成基本数据类型进行比较。
对于equals方法,如果参数是基本数据类型变量,则会自动装箱,再进行比较。如果参数是对象,则直接进行比较。如果两个对象不是同一种类型,那么返回false,因此DEF错。

2.下列选项中哪个是正确的输出结果()

public class Test03 {
    public static void main(String[] args) { 
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
        System. out.println( f1 == f2);
        System. out.println( f3 == f4);
    }
}

A TRUE TRUE
B FALSE TRUE
C TRUE FALSE
D FALSE FALSE

答案:C
笔记:
摘自牛客网用户“tgp”:
当我们给一个Integer赋予一个int类型的时候会调用Integer的静态方法valueOf。
具体来看看Integer.valueOf的源码

public static Integer valueOf(int i) {

        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}

在IntegerCache中cache数组初始化如下,存入了-128 - 127的值

cache = new Integer[(high - low) + 1];
int j = low;
for( int k = 0; k < cache.length ; k ++)
    cache[k] = new Integer(j ++);

从上面我们可以知道给Interger 赋予的int数值在-128 - 127的时候,直接从cache中获取,这些cache引用对Integer对象地址是不变的,但是不在这个范围内的数字,则new Integer(i) 这个地址是新的地址,不可能一样的。

3.以下输出结果为false的是:()

Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);

A System.out.println(i01==i02);
B System.out.println(i01==i03);
C System.out.println(i03==i04);
D System.out.println(i02==i04);

答案:C
笔记:
当int类的值和Integer类型的值进行比较时,Integer会自动拆箱变成int类型。当当我们给一个Integer赋予一个int类型的时候会调用Integer的静态方法valueOf。故ABD都对。
而new出来的Integer对象,地址肯定与其他的不同,i03和i04都是Integer类型,比较的是地址,因此肯定是返回false。

4.经过强制类型转换以后,变量a,b的值分别为多少?

short a =128byte b =(byte) a;

A 128 127
B 128 - 128
C 128 128
D 编译错误

答案:B
笔记:

5.在 Java 中,属于整数类型变量的是()
A single
B double
C byte
D char

答案:C
笔记:
8个基本数据类型可以分为4类:
整数类型:byte,short,int,long
浮点型:float,double
布尔型:boolean
字符型:char

6.下面哪些赋值语句是正确的()
A long test=012;
B float f=-412;
C int other =(int)true;
D double d=0x12345678;
E byte b=128;

答案:ABD
笔记:
对于AB,test和f都是基本数据类型,赋值符号右边是int类型,会自动升级成相应类型。
要注意的是,

long test = 012;
Long test2 = 012;   //编译出错,赋值符号右边是int类型会自动装箱变成Integer类型,由于两边类型不一致,导致出错
Long test3 = 012L;  //正确写法,加上L,表示long类型,long类型自动装箱变成Long类型,就可以正常赋值了

float f = -412;
float f1 = -412.0;  //编译出错,浮点数默认是double类型,因此无法将double类型的值赋给比他小的float类型变量,因此,编译无法通过。
Float f2 = -412;        //编译出错,赋值符号右边是int类型会自动装箱变成Integer类型,由于两边类型不一致,导致出错
Float f3 = -412.0;  //编译出错,赋值符号右边是double类型会自动装箱变成Double类型,由于两边类型不一致,导致出错
Float f3 = -412f;   //正确写法,加上f,表示float,float类型自动装箱变成Float类型,就可以正常赋值了

至于D,布尔类型的变量无法与其他基本数据类型变量进行相互赋值。
至于E,byte类型的范围是[-128,127],将128赋给byte类型的变量,编译将无法通过:Type mismatch: cannot convert from int to byte

7.设有下面两个赋值语句:

a = Integer.parseInt("1024");
b = Integer.valueOf("1024").intValue();

下述说法正确的是()
A a是整数类型变量,b是整数类对象。
B a是整数类对象,b是整数类型变量。
C a和b都是整数类对象并且它们的值相等。
D a和b都是整数类型变量并且它们的值相等。

答案:D
笔记:
Integer.parseInt方法是将String变成int类型;
Integer.valueOf方法是将String类型变成Integer类型;
Integer的intValue方法是将Integer类型变成int类型。

8.设int x=1,float y=2,则表达式x/y的值是:()
A 0
B 1
C 2
D 以上都不是
答案:D
笔记:
在进行运算之前,两边的变量会通过自动转换进行统一,因此int类型的变量x会自动向上转换成float类型,因此最后得到的结果的类型也是float类型,结果为0.5。

9.下面赋值语句中正确的是()
A double d=5.3e12;
B float f=11.1;
C int i=0.0;
D Double oD=3;
答案:A
笔记:
对于B,浮点数11.1默认的是double类型,而float小于double,因此编译不通过。修改如下:float f = 11.1f;
对于C,理由同上。
对于D,整数类型的3是int型,自动装箱变成Integer,由于和赋值符号左边的Double不一致,所以编译不通过,修改如下:double oD = 3;

十九、String、StringBuffer、StringBuilder

1.java中,StringBuilder和StringBuffer的区别,下面说法错误的是()
A StringBuffer是线程安全的
B StringBuilder是非线程安全的
C StringBuffer对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。
D 效率比较String

二十、java编译与运行

1.关于java编译和运行命令叙述不正确的是?
A 运行“java Scut.class”
B 运行“java Scut”
C 运行“javac Scut.java”的输出文件是Scut.class
D java这个命令的运行对象是Scut.class

答案:A
笔记:
譬如有个文件叫 Student.java,
执行编译命令:javac Student.java,生成了Student.class,
执行运行命令:java Student。

2.下列哪个选项是Java调试器?如果编译器返回程序代码的错误,可以用它对程序进行调试()
A java.exe
B javadoc.exe
C jdb.exe
D javaprof.exe

答案:C
笔记:
javac.exe是编译.java文件
java.exe是执行编译好的.class文件
javadoc.exe是生成Java说明文档
jdb.exe是Java调试器
javaprof.exe是剖析工具

3.命令javac-d参数的用途是?()
A 指定编译后类层次的根目录
B 指定编译时需要依赖类的路径
C 指定编译时的编码
D 没有这一个参数

答案:A
笔记:

引用牛客网用户“lemonn”的一段话:

-d 目录设置类文件的目标目录。如果某个类是一个包的组成部分,则 javac 将把该类文件放入反映包名的子目录中,必要时创建目录。例如,如果指定 -d c:\myclasses 并且该类名叫 com.mypackage.MyClass,那么类文件就叫作 c:\myclasses\com\mypackage\MyClass.class。
若未指定 -d 选项,则 javac 将把类文件放到与源文件相同的目录中。
注意: -d 选项指定的目录不会被自动添加到用户类路径中。

二十一、数组的声明

1.Which statement declares a variable a which is suitable for referring to an array of 50 string objects? ()
A char a[][];
B String a[];
C String[] a;
D Object a[50];
E String a[50];
F Object a[];

答案:BCF
笔记:
在java中,声明一个数组时,不能直接限定数组长度,只有在创建实例化对象时,才能给定数组长度。

2.以下二维数组声明合法的是( )
A char[2][3] ch = new char[][]
B char[2][] ch = new char[][3]
C char[][] ch = new char[2][3]
D char[][] ch = new [2]char[3]

答案:C
笔记:
引用牛客网用户“Specia…”的一段话:

写一下个人理解的数组声明为什么这么写?
第一个就是为什么左边不用标大小,而右边需要标大小?
首先数组一个对象,它不属于任何类,由jvm在运行期间在堆中创建并继承object,同时添加length属性。由于数组对象所占的内存在堆上,所以在声明时应明确告诉jvm自己所占的大小,方便分配,又因为数组对象的引用在栈中,所以声明时左边就无需标大小,之所以写成2个括号,就是为了表明这个引用指向堆中的二维数组。
第二个就是为什么右边数组可以只声明几行,无需声明没行的大小?
大概jvm在运行期间会根据行数分配对应的可扩展空间,方便每一行进行扩充。其实又可以按c语言那样理解,行其实又是一种引用,行首地址又代表一个一维数组。
因此,如果有一个二维数组ch:char[][] ch = new char[2][3],那么ch.length得到的是二维数组的行数,ch[0].length得到的是二维数组的列数

二十二、Java Web

1.常用的servlet包的名称是?()
A java.servlet
B javax.servlet
C servlet.http
D javax.servlet.http

答案:BD
笔记:
java 是java j2sdk 中的类库,也就是Java Development kit 。 它提供也一些基础的东西,如io库、桌面程序的类库,如awt。集合库(如Collection、List、Map)。等这些最基础的类库。
javax是java的扩展包,如j2ee 中的类库,包括servlet,jsp,ejb,数据库相关的一些东西,xml的等。
javax包里关于Servlet的全部包如图所示:

其中,最常用的就是javax.servlet和javax.servlet.http这两个包

2.下面有关servlet service描述错误的是?()
A 不管是post还是get方法提交过来的连接,都会在service中处理
B doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的
C service()是在javax.servlet.Servlet接口中定义的
D service判断请求类型,决定是调用doGet还是doPost方法

答案:B
笔记:
GenericServlet 抽象类 给出了设计 servlet 的一些骨架,定义了 servlet 生命周期,还有一些得到名字、配置、初始化参数的方法,其设计的是和应用层协议无关的。doGet和doPost 底层是基于 http实现的,因此是在javax.servlet.HtppServlet中实现的。
参考图片:

3.(多选题)下面有关servlet的层级结构和常用的类,说法正确的有?
A GenericServlet类:抽象类,定义一个通用的、独立于底层协议的Servlet。
B 大多数Servlet通过从GenericServlet或HttpServlet类进行扩展来实现
C ServletConfig接口定义了在Servlet初始化的过程中由Servlet容器传递给Servlet得配置信息对象
D HttpServletRequest接口扩展ServletRequest接口,为HTTP Servlet提供HTTP请求信息

答案:ABCD
笔记:
摘自牛客网用户“牛客143068号”:
Java中有关servlet的层级结构和常用的类的描述:
GenericServlet类:抽象类,定义一个通用的、独立于底层协议的Servlet。
大多数Servlet通过从GenericServlet或HttpServlet类进行扩展来实现
ServletConfig接口定义了在Servlet初始化的过程中由Servlet容器传递给Servlet得配置信息对象
HttpServletRequest接口扩展ServletRequest接口,为HTTP Servlet提供HTTP请求信息
HttpServlet是GenericServlet的子类。
GenericServlet是个抽象类,必须给出子类才能实例化。它给 出了设计servlet的一些骨架,定义了servlet生命周期,还有一些得到名字、配置、初始化参数的方法,其设计的是和应用层协议无关的,也就是说 你有可能用非http协议实现它。
HttpServlet是子类,当然就具有GenericServlet的一切特性,还添加了doGet, doPost, doDelete, doPut, doTrace等方法对应处理http协议里的命令的请求响应过程。
一般没有特殊需要,自己写的Servlet都扩展HttpServlet 。

4.从以下哪一个选项中可以获得Servlet的初始化参数? ()
A Servlet
B ServletContext
C ServletConfig
D GenericServlet

答案:C
笔记:
通过ServletConfig接口中的getInitParameter(java.lang.String name)方法。
ServletConfig和ServletContext的比较:
ServletContext对象:servlet容器在启动的时候会加载Web应用,并为每个web应用创建唯一的ServletContext对象,在ServletContext对象中存放共享数据。
ServletConfig对象:用于封装servlet的配置信息,从一个servlet被实例化后,对任何客户端在任何时候访问有效,一个servlet的ServletConfig对象不能被另一个servlet访问。

5.在Web应用程序的文件与目录结构中,web.xml是放置在( )中
A WEB-INF目录
B conf目录
C lib目录
D classes目录

答案:A
笔记:

6.java如何接收request域中的参数?()
A request.getRequestURL()
B request. getAttribute()
C request.getParameter()
D request.getWriter()

答案:C
笔记:
from牛客网用户“allensimon”:

request域代表一次请求处理的过程,就是从客户端到服务端的一次请求的过程。request.getParameter()获取HTTP提交过来的数据。
而request.getAttribute()方法返回reques,sessiont范围内存在的对象。

7.下面有关forward和redirect的描述,正确的是() ? 1/1
A forward是服务器将控制权转交给另外一个内部服务器对象,由新的对象来全权负责响应用户的请求
B 执行forward时,浏览器不知道服务器发送的内容是从何处来,浏览器地址栏中还是原来的地址
C 执行redirect时,服务器端告诉浏览器重新去请求地址
D forward是内部重定向,redirect是外部重定向
E redirect默认将产生301 Permanently moved的HTTP响应

答案:BCD
笔记:
如果没有指定redirect的返回参数,则默认重定向是”临时性的”(HTTP status 302)。
from牛客网用户“盛远之”:

1.从地址栏显示来说
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
2.从数据共享来说
forward:转发页面和转发到的页面可以共享request里面的数据.
redirect:不能共享数据.
3.从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.
4.从效率来说
forward:高.
redirect:低.

二十三、集合框架

1.以下代码对其执行后,NumberList里的元素依次为()

List<Integer> list = new ArrayList<Integer>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
list.add(5);
for(int i = 0;i<list.size();++i){
    int v = list.get(i);
    if (v % 2 == 0)
        list.remove(v);
}
System.out.println(list);

A 2,4,1,3,5
B 2,1,3,5
C 4,1,3,5
D 会出现越界情况

答案:D
笔记:
List接口中有一个remove方法:E remove(int index);,很明显,参数index表示的是数组下标;
List接口的父接口Collection中也有一个remove方法:boolean remove(Object o);,参数o表示的是元素内容
因此,当我们调用list的remove方法且传入的参数是int类型时,实际上调用的是List接口中的remove方法。
因此在第1次for循环时,调用了remove方法移除了第3个元素,即元素1,这时list的元素只剩下4个。第二轮循环,调用remove方法移除第5个元素,因此抛出了IndexOutOfBoundsException异常。

2.以下哪些继承自 Collection 接口()
A List
B Set
C Map
D Array

答案:AB
笔记:
Collection中存放的是一组各自独立的对象,Map中存放的是“键-值”对象。

二十四、反射

1.下面的代码,其中”c.getDeclaredMethods”的作用是()

import java.lang.reflect.*;
public class DumpMethods{
    public static void main(String[] args) {
        try {
            Class c=Class.forName(args[0]);
            Method m[]=c.getDeclaredMethods();
            for (int i = 0; i < m.length; i++) {
                System.out.println(m[i].toString());
            }
        } catch (Throwable e) {
            System.err.println(e);
        }
    }
}

A 取得类的公有方法对象
B 取得类的所有公有方法名称
C 取得类的所有方法对象
D 以上选项都不正确

答案:D
笔记:
public Method[] getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。
public Method[] getDeclaredMethods()对象表示的类或接口声明的所有方法, 包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。

2.(多选题)JAVA反射机制主要提供了以下哪些功能?()

A 在运行时判断一个对象所属的类
B 在运行时构造一个类的对象
C 在运行时判断一个类所具有的成员变量和方法
D 在运行时调用一个对象的方法

答案:ABCD
笔记:
摘自牛客网用户“牛客-007”:
普通的java对象是通过new关键字把对应类的字节码文件加载到内存,然后创建该对象的。
反射是通过一个名为Class的特殊类,用Class.forName(“className”);得到类的字节码对象,然后用newInstance()方法在虚拟机内部构造这个对象(针对无参构造函数)。
也就是说反射机制让我们可以先拿到java类对应的字节码对象,然后动态的进行任何可能的操作,
包括
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
这些都是反射的功能。
使用反射的主要作用是方便程序的扩展。

二十五、其他

1.下面哪个选项不能用来替代代码中的第三行()

public abstract class MyClass {
     public int constInt = 5;
     //add code here
     public void method() {} 
} 

A. public abstract void method(int a);
B. consInt=constInt+5;
C. public int method();
D. public abstract void anotherMethod(){}

答案:A
笔记:
小心B,B是一个赋值运算,不能出现在类中,只能出现在方法、static块、普通块中。

2.第三行将输出什么?

public class SwitchTest{//1
    public static void main(String[] args) {//2
        System.out.println("value="+switchit(4));//3
    }//4
    public static int switchit(int x) {
        int j=1;
        switch (x) {
        case 1:j++;
        case 2:j++;
        case 3:j++;
        case 4:j++;
        case 5:j++;
        default:j++;
        }
        return j+x;
    }
}

A. value=6
B. value=8
C. value=3
D. value=5
E. value=4

答案:B
笔记:
当某一个case满足条件,如果没有break的话,会继续往下执行后面的语句。如果default语句放在最后,那么不管是否有一个case满足条件,default语句都会执行。
如果default语句放在最前,且所有case都不满足,就会执行default语句,并执行之后的每个case语句(前提是没有使用break)
要注意的是,default语句并不一定会执行,有一种情况default语句是不执行的:当满足条件是发生在default语句之后的case语句,则不会返回去执行default语句。

3.在java7中,下列不能做switch()的参数类型是?
A 整型
B 枚举类型
C 字符串
D 浮点型

答案:D
笔记:
switch(expr)的参数支持的类型有:
int类型以及小于int的类型(即byte、char、short)以及相应的包装类类型
枚举类型Enum
String类型,自java7开始支持。
注意,不支持long类型、也不支持浮点型类型

4.代码的运行结果是()

package com.sunline.java;
public class A implements B extends C{
    public static void main(String args[]){
        System.out.println("hello sunline!");
    }
}

A 在控制台打印hello sunline!
B 报异常java.lang.NullPoninterException
C 编译报错
D 报异常java.lang.RuntimeExcception

答案:C
笔记:
先继承再实现,如果实现了多个接口,接口间使用逗号隔开。另外,注意继承和实现的关键字,是有s的,extends、implements。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页