Java面试题
文章目录
- Java面试题
- Java基础以及api
- 程序题
- 1.下面sum的值是( D )
- 2.下面程序的运行结果( A )
- 3.若x是`float`类型变量,`x=10/4;` 则`x`的值是( B )
- 4.以下程序的输出结果是(`x= 99 , x= 201`)
- 5.以下程序的输出结果是(`x= 200`)
- 6.以下程序的输出结果是(`200 300 400 500`)
- 7.以下程序的输出结果是(`x= 200`)
- 8.String str = new String(“abc”)创建了几个StringObject
- 9.String str = new String(“ab” +“c” + “d”)创建了几个String对象
- 10.下面程序的运行结果( C )
- 11.下面哪个关键字,使类不能再被其他类继承(C)
- 12.下面程序的运行结果( C )
- 13.下面程序的运行结果( C )
- 14.下面哪些是合法标识符( A 、B、E)
- 15.已知如下的命令执行 `java MyTest a b c`,请问哪个选项是正确的(C )
- 16.选项中哪个放到x处可保证程序正常编译( C )
- 17.下面程序的运行结果( D )
- 18.下面程序的运行结果( D )
- 19.请指出以下代码是否有错误及其控制台输出
- 20.下面程序的运行结果( A )
- 21.下面程序的运行结果( B )
- 22.下面程序在JDK1.8的环境下,描述正确的是( A 、D)
- 23.下面那些异常是检查异常,需要在编写程序时声明( C )
- 24.下面程序,当输入2时返回值是多少( D )
- 25.选项中哪一行代码可以替换题目中`//add code here` 而不产生编译错误( A )
- 26.下面程序在执行`new Child("mike")`的时候输出结果( D )
- 27.下面程序的运行结果
- 28.下面程序的运行结果( B )
- 29.下面程序的运行结果( B )
- 30.哪个语句创建了一个数组实例( A )
Java基础以及api
程序题
1.下面sum的值是( D )
int sum = 1;
for (int i = 0; i <10; i++){
i++; //1 3 5 7 9
sum += i; //1+1+3+5+7+9
}
System.out.println(sum);
A.46 B.24 C.45 D.26
2.下面程序的运行结果( A )
Integer a = 300; //自动装箱 a = new Integer(300)
Integer b = 300; //自动装箱 b = new Integer(300)
int c = 300 ;
System.out.println(a == b); // false
System.out.println(a == c); // true == 两侧为引用类型和基本数据类型,将自动拆箱,进行数值比较
A.false ; true
B.false ; false
C.true ; false
D.true ; true
//自动拆装箱操作:从JDK1.5开始提供,自动拆箱是在编译期完成,自动拆装箱底层都是通过调用方法来完成
xx.java: Integer a = 100; int x = a;
xx.class: Integer a = Integer.valueOf(100); int x = a.intValue();
//valueOf(): Integer底层实现是:判断整数的值,是否处于-128~127之间,若处于该区间,则返回常量池中的Integer对象,不会新建,若整数不处于该区间,此时底层 new Integer(i),为新创建的对象
// 基本数据类型的包包装类中 所有的整数都有常量池,小数(浮点型)、布尔是没有常量池的
3.若x是float
类型变量,x=10/4;
则x
的值是( B )
A. 2 B. 2.0 C. 2.5 D. 编译错误
4.以下程序的输出结果是(x= 99 , x= 201
)
public class HasStatic() {
private int x = 100;
public static void main(String[] args) {
HasStatic has1 = new HasStatic();
has1.x++;
HasStatic has2 = new HasStatic();
has2.x += has1.x;
has1 = new HasStatic();
has1.x--;
System.out.println("x=" + has1.x); //99
System.out.println("x=" + has2.x); //201
}
}
//考点: 实例变量是属于实例的,会随着实例的重新创建而重新初始化
5.以下程序的输出结果是(x= 200
)
public class HasStatic() {
private static int x = 100;
public static void main(String[] args) {
HasStatic has1 = new HasStatic();
has1.x++;
HasStatic has2 = new HasStatic();
has2.x += has1.x;
has1 = new HasStatic();
has1.x--;
HasStatic.x--;
System.out.println("x=" + has1.x); //200
}
}
//考点: static变量是属于类的,在类加载时期完成初始化,且只初始化一次
6.以下程序的输出结果是(200 300 400 500
)
public class Test{
static{
System.out.println("200");
}
public Test(){
System.out.println("500");
}
{
System.out.println("300");
}
public static void main(String[] args) {
new Test();
}
{
System.out.println("400");
}
}
// static代码块 -> 代码块(构造块) -> 构造方法
7.以下程序的输出结果是(x= 200
)
String s1 = "abc", s2 = "def", s3 = "abcdef";
String s4 = s1 + s2;
String s5 = "abc" + "def";
String s6 = new String("abc");
System.out.println(s1 == s6); //false
System.out.println(s3 == s4); //false
System.out.println(s3 == s5); //true
//1.字符串变量之间的拼接在运行期完成,通过StringBuilder进行拼接,StringBuilder的toString()方法底层是new String
//2.字符串字面量之间的拼接在编译期完成
8.String str = new String(“abc”)创建了几个StringObject
//2个 一个是 new String, 另一个是 字面量 “abc”
9.String str = new String(“ab” +“c” + “d”)创建了几个String对象
//2个 一个是 new String, 另一个是 字面量 “abcd” 是因为字符串字面量之间的拼接是在编译期完成的
//在 .class文件中代码为 String str = new String("abcd")
10.下面程序的运行结果( C )
abstract class MineBase {
abstract void amethod();
static int i;
}
public class Mine extends MineBase {
public static void main(String[] args) {
int[] ar = new int[5];
for (i = 0; i < ar.length; i++) {
System.out.println(ar[i]);
}
}
}
A. 打印5个0
B. 编译出错,数组ar[]必须初始化
C. 编译出错,Mine应声明为abstract
D. 出现IndexOutOfBoundsException异常
11.下面哪个关键字,使类不能再被其他类继承(C)
A.static B.finally C.final D.instance
final
:是一个修饰符
- 类:类不能被继承
- 方法:方法不能被重写
- 变量:可以是成员变量也可以是局部变量,变量值一旦初始化不可改变
- 修饰成员变量:必须在声明同时初始化
- 修饰局部变量:可以先声明再初始化
static
:是一个修饰符
- 成员变量:在类加载时期完成初始化,且只初始化一次,通过类名调用,也可通过对象调用不过不推荐
- 方法:通过类名调用静态方法,static方法内部不能使用
this
、super
关键字(静态方法中是通过类名来调用方法的,不存在通过实例来调用,this
是引用,指向调用当前方法的对象,super
指向的是父类对象,所以都不存在,而非静态方法默认存在this
、super
关键字)- 代码块:在类加载时期执行结束,且只执行一次
注:static可以修饰类,但必须是内部类,如
LinkedList
的内部类Node
,其本质是修饰类中的成员,内部类就是类中的成员
finally
:和try...catch
配合使用,finally
块中的代码不论之前是否有异常出现,都会执行,通常在finally
块中保存释放资源的代码
instanceof
:判断某个实例是否属于某种类型eg:
if(per instanceof Person)
12.下面程序的运行结果( C )
public class Ppvg{
public static void main(String[] args) {
Ppvg p = new Ppvg();
int x = p.flition();
System.out.println(x);
}
public int flition(){
try{
FileInputStream din = new FileInputStream("Ppvg.java");
din.read();
}catch(IOException e){
System.out.println("flytwick");
return 99;
}finally{
System.out.println("flition");
}
return -1;
}
}
A. 程序正常运行并输出: "flition" 和 99
B. 程序正常运行并输出: "flytwick"、"flition" 和 -1
C. 程序正常运行并输出: "flytwick"、"flition" 和 99
D. 在编译时产生错误,因为flition方法要求返回两个值
//以上代码执行流程
/*
9行 执行时会报异常,若通过输入流直接写入文件名称,可能出现找不到,因为直接找的是当前项目下,而类存在于src下
抛出异常后被 11行 捕获异常 进入 catch块 输出 12行内容 "flytwick"
如果 try...catch块中有 finally ,finally必执行,则会在 catch块返回时 先进入 finally块 输出 15行内容 "flition"
最后返回 catch块 执行 13行 返回 99 程序结束
所以最终输出 "flytwick"、"flition" 和 99
*/
13.下面程序的运行结果( C )
public class Ppvg{
public static void main(String[] args) {
Ppvg p = new Ppvg();
int x = p.flition();
System.out.println(x);
}
public int flition(){
int i = 99;
try{
FileInputStream din = new FileInputStream("Ppvg.java");
din.read();
}catch(IOException e){
System.out.println("flytwick");
return i;
}finally{
i++;
System.out.println("flition");
}
return -1;
}
}
A. 程序正常运行并输出: "flition" 和 99
B. 程序正常运行并输出: "flytwick"、"flition" 和 100
C. 程序正常运行并输出: "flytwick"、"flition" 和 99
D. 在编译时产生错误,因为flition方法要求返回两个值
//以上代码执行流程
/*
10行 执行时会报异常,若通过输入流直接写入文件名称,可能出现找不到,因为直接找的是当前项目下,而类存在于src下
抛出异常后被 12行 捕获异常 进入 catch块 输出 13行内容 "flytwick" ,此时 14行 返回时 i=99
如果 try...catch块中有 finally ,finally必执行,则会在 catch块返回时 先进入 finally块 执行 16行 i=100 ,输出 17行内容 "flition"
最后返回 catch块 执行 14行,此时到底 返回100还是99 答案是返回 99 程序结束
其涉及内部操作,当catch一开始要返回时,因为finally中的代码必须执行,此时catch中的return就会暂停,但其实是知道要返回的值是多少,相当于在这里会拍一个快照,在之后执行任何操作都不会影响这个快照,之后返回的值还是这个快照中的值,而finally修改的是方法里的值,返回的是之前记录的值,所以finally中的操作属于附带操作
所以最终输出 "flytwick"、"flition" 和 99
*/
14.下面哪些是合法标识符( A 、B、E)
A. $persons
B. TwoUsers
C. *point
D. this
E. _ending
F. 2_4dis
//所以 标识符 是由 数字、字母、_、$ 组成,且数字不能开头,且不能使用Java已经定义好的关键字
15.已知如下的命令执行 java MyTest a b c
,请问哪个选项是正确的(C )
A. args[0]="MyTest a b c"
B. args[0]="MyTest"
C. args[0]="a"
D. args[1]="b c"
//关于 java命令 在jdk目录下bin文件夹下的可执行文件 就是一条条命令
/*搭建Java环境: 安装JDK和配置JDK环境变量
JAVA_HOME: JDK的安装路径
path: bin目录的路径
classpath: . 类库
*/
/*
java 命令 关于运行,运行字节码文件的名称
java class_name --对某个类运行,执行其main方法
javac 命令 关于编译,指定java源文件进行编译产生.class文件
javac xx.java --对源文件进行遍历
如果想传参 只需 在多个参数间 空格 即可
*/
16.选项中哪个放到x处可保证程序正常编译( C )
interface Foo{
int bar();
}
public class Sprite{
public int fubar(Foo foo){
return foo.bar();
}
public void testFoo(){
fubar();//此处为X
}
}
A. Foo{ public int bar({return 1;}}
B. new Foo{public int bar({return 1;}}
C. new Foo(){public int bar({return 1;}}
D. new class Foo{public int bar(ireturn 1;}}
//接口 中的方法是抽象方法
//匿名内部类
new Foo(){ //创建匿名内部类对象
//重写抽象方法
bar(){
//...
}
}
17.下面程序的运行结果( D )
class A{
void foo() throw Exception{
throw new Exception();
}
}
class SubA extends A{
void foo(){
System.out.println("A");
}
}
class Tester{
public static void main(String[] args) {
A a = new SubA();
a.foo();
}
}
A. A
B. A ,抛出Exception
C. 编译失败,7行出现错误
D. 编译失败,14行出现错误
E. 无输出,但抛出Exception
//重写的规则: 2同2小1大
/*
2同: 方法名相同,参数列表相同
2小: 子类方法返回值类型小于等于父类。子类方法抛出的异常小于等于父类(抛出异常数量,子类方法抛出异常类型可以是父类抛出异常类型的子类)
1大: 子类重写方法的访问控制修饰符必须大于等于父类
*/
/*
通过父类类型的引用调用重写的方法
运行期:一定调用的是重写后的方法,即是子类的
编译期:调用到的是数据类型所属类的方法,看的是左侧的类型,即调用的方法是父类中的方法
所以本题中 14行 需要捕获或抛出异常
*/
18.下面程序的运行结果( D )
static void test() throws RuntimeException{
try{
System.out.print("test");
throw new RuntimeException();
}catch(Exception e){
System.out.print("exception"); //这里已经捕获了异常
}
}
public static void main(String[] args) {
try{
test();
}catch(RuntimeException ex){
System.out.print("runtime"); //已经没有异常要捕获了
}
System.out.print("end");
}
A. test end
B.编译失败
C. test runtime end
D. test exception end
19.请指出以下代码是否有错误及其控制台输出
public class test{
private static Integer b; //null
public static void main(String[] args) {
int a = 10;
print(a);
print(b); //编译期无异常,运行时异常 此时会报空指针异常
b = a;
print(b);
}
private static void print(Integer value){
int add = value + 5; //value.intValue()
System.out.println("add value = " + add);
}
}
//最终 先输出 add value = 15,然后抛出 NullPointerException
20.下面程序的运行结果( A )
public class A implements B{
public static void main(String[] args) {
int i;
A c1 = new A();
i = c1.K; //正常通过类名、接口名访问;通过实例访问静态常量可以,不过不建议
System.out.print("i = " + i);
}
}
interface B{
int K = 10;
}
A. i = 10
B.编译失败
21.下面程序的运行结果( B )
public static void main(String[] args) {
Thread t = new Thread(){
public void run(){
pong();
}
}
t.run(); //并不是启动线程,直接调用run() 只是个普通方法,所以只有一个线程
System.out.print("ping");
}
static void pong(){
System.out.print("pong");
}
A. pingpong
B.pongping
C. pingpong 和 pongping 都有可能
D. 都不输出
//start()和run()
// start()表示启动线程
// 直接调用run()方法只是普通方法的调用,线程并没有启动
22.下面程序在JDK1.8的环境下,描述正确的是( A 、D)
interface Er{
double PI = 3.14;
void tongdian();
public default void duandian(){
}
}
interface Ar{
public default void duandian(){
}
}
class Dfqc implements Er,Ar{
public void tongdian(){
System.out.print("通电函数" + PI);
}
public class Test{
public static void main(String[] args) {
Dfqc t = new Dfqc();
t.tongdian();
t.duandian();
}
}
}
A.在类Dfqc中,没有实现duandian()方法,编译不通过
B.在接口中定义的PI没有用final修饰,不是常量,可以更改数值
C.编译正确,duandian()方法是接口中定义的普通方法,在JDK1.8后允许,实现类对象可以直接调用
D.编译错误,duandian()方法在卜接口中均存在,类Dfqc实现了两个接口,该类中必须重写duandian()编译才正确
/*
JDK1.8的新特性
1. lambda表达式
2. 新日期 LocalDateTime.now()
3. 接口中可以定义默认方法和static方法
4. :: 方法引用
lambda表达式作用: 为简化代码而出现 ()-> {}
1.实现功能性接口(函数式接口)
功能性/函数式接口: 接口中只有一个抽象方法,可以有多个静态方法,默认方法且在接口上方有注解@FunctionalInterface
lambda表达式各部分代表的意义:
(): 重写方法的参数列表
{}: 重写方法的方法体
lambda表达式各部分的简化:
(): 参数列表中的数据类型都可以省略;若参数列表中只有一个参数,此时()可以省略,若参数列表无参或有多个参数,此时()都不可以省略
{}: 若体部分只有一行代码,此时{}可以省略,若体部分只有一行代码且有return,此时return也可以省略
2.对集合进行遍历
集合若想使用lambda表达式遍历,需要集合对lambda的支持,支持是指:看集合中是否提供forEach(),若有则可以使用lambda对集合进行遍历
list.forEach(str->System.out.println(str));
set.forEach(str->System.out.println(str));
map.forEach((k, v)->System.out.println(k+"-"+v));
新日期 LocalDateTime.now()
LocalDateTime time = LocalDateTime.now();
System.out.println(time);
旧日期 Date date = new Date();
接口中可以定义默认方法和static方法
JDK1.8之前,接口中有的成员只有:
常量(接口为其提供了默认修饰符) public static final
抽象方法(接口为其提供了默认修饰符) public abstract
JDK1.8开始,允许在接口中定义默认方法和static方法:
默认方法需要添加修饰符 default,通过接口的实现类对象来调用方法
若一个实现类实现了两个接口,且两个接口中有相同的默认方法,此时在实现类汇总必须对该方法进行重写,否则编译不通过
静态方法 和平时的static方法定义是相同的,通过接口名调用static方法即可
:: 方法引用: 用于简化lambda表达式的,不做其他
简化的前提:lambda表达式中的参数会作为参数传递给体中调用的方法,且是所有参数都传递给调用的方法,此时使用 :: 来简化lambda表达式
(a,b,c)->{A.test(a,b,c)} ==》 A::test
1. static方法引用
1.定义功能性接口
2.出现接口作为参数出现
3.使用::简写lambda表达式
2. 实例方法引用
3. 构造方法引用
4. 数组的构造方法引用
*/
23.下面那些异常是检查异常,需要在编写程序时声明( C )
A.NullPointerException
B.ClassCastException
C.FileNotFoundException
D.IndexOutOfBoundsException
//所有异常的父类 Throwable,其子类有 Exception、Error
/*
Error:
栈内存溢出异常: StackOverFlowError
递归没有出口、递归深度太深
堆内存溢出异常: OutOfMemoryError
创建的对象太大、内存泄漏的一直累积
Exception:
检查异常: 在编译过程中可检测到的,且必须处理的异常,若不处理编译不通过
文件找不到异常: FileNotFoundException
IO异常: IOException
中断异常: InterruptedException
解析异常: ParseException
类找不到异常: ClassNotFoundException
特点:所有的检查异常一定是在方法声明位置通过throws来抛出了异常类型
运行时异常: 在编译期检测不到,是在运行期出现的异常
空指针异常: NullPointerException
类转换异常: ClassCastException
下标越界异常: IndexOutOfBoundsException
数字转换异常: NumberFormatException
throws 和 throw 的区别:用法不一样
throws: 作用于方法声明位置,抛出的是异常类型
throw: 作用于方法体中,抛出的是异常对象
*/
24.下面程序,当输入2时返回值是多少( D )
public static int getValue(int i){
int result = 0;
switch(i){
case 1:
result = result + i;
case 2:
result = result + i * 2; //分支中没有break; 则继续向下执行
case 3:
result = result + i * 3;
return result;
}
}
A. 2 B. 0 C. 4 D. 10
25.选项中哪一行代码可以替换题目中//add code here
而不产生编译错误( A )
public abstract class Myclass{
public int constInt = 5;
//add code here
public void method(){
}
}
A.public abstract void method(int a); //重载
B.constInt = constInt + 5; //执行代码不能直接写在类的成员位置,必须存在{}中
C.public int method(); //抽象方法没有abstract; 和类中的method方法签名完全一致,不能存在同一个类中
D.public abstract void anotherMethod(){} //抽象方法不能有方法体
/*
重写:是出现在父子类中
重载:是指在同一个类中出现的方法名相同,参数列表不同的方法,重载和方法的返回/访问控制修饰符都无关
*/
26.下面程序在执行new Child("mike")
的时候输出结果( D )
class People(){
String name;
public People(){ //这里隐藏了super();
System.out.print(1);
}
public People(String name){ //这里隐藏了super();
System.out.print(2);
this.name = name;
}
}
class Child extends People(){
People father;
public Child(String name){ //这里隐藏了super();
System.out.print(3);
this.name = name;
father = new People(name + ":F");
}
public Child(){ //这里隐藏了super();
System.out.print(4);
}
}
A. 312 B. 32 C. 432 D. 132
//构造方法的第一行代码永远都是super()
27.下面程序的运行结果
public class SubCls extends SuperCls{
int a = 6;
public SubCls(){
test();
}
public void test(){
System.out.println(a);
}
public static void main(String[] args){
new SubCls();
}
}
class SuperCls{
int a = 8;
public SuperCls(){
test();
}
public void test(){
System.out.println(a);
}
}
//运行结果: 0 6
/*
成员变量不进行初始化的话也会有默认初始值,在刚创建好对象时就赋有初始值
人为初始化后,仍会有默认初始值
关于成员变量人为初始化的时机,在构造方法里面进行初始化
在运行期时,若一个方法在父子类中都存在,到底调用谁,看运行期创建的对象
若父子类中都存在一个相同的变量,值不同,则子类访问子类的,父类访问父类的
*/
28.下面程序的运行结果( B )
class Base{
Base(){
System.out.println("Base");
}
}
public class Alpha extends Base{
public static void main(String[] args){
new Alpha();
new Base();
}
}
A.Base
B.Base Base
C. 编译失败
D.代码运行但没输出
E. 运行时抛出异常
//子类构造方法中第一行是 super()
29.下面程序的运行结果( B )
public class Test1{
public static void main(String[] args){
System.out.println("返回值为:" + new Test1().test());
}
public int test(){
int i = 1;
try{
System.out.println("try中的i值为:" + i); // 1
return i; // 1 返回快照 1
}finally{
++i; // 2
System.out.println("finally中的i值为:" + i); // 2
}
}
}
A. 1 1
B. 1 2 1
C. 1 2 2
D. 1 2
30.哪个语句创建了一个数组实例( A )
A.int[] i = new int[15];
B.float f = new float[20]; //左边是变量,右边是对象 类型不匹配
C. char[] c = "Some String"; //左边是字符数组,右边是字符串 类型不匹配
D.int a[][] = {3,12,15}{1123,53,5}; //二维数组
//数组中的元素类型可以是任意的(机泵数据类型,引用类型),而数组本身就是引用类型,若数组中的元素为数组类型,则出现了二维数组/多维数组
/*
定义:
初始化方式1:直接赋值
int[][] ary = {{1,3},{4,25,1},{123,5,12,54}};
初始化方式2:若二维数组的长度一致,此时可以采用以下方法
int[][] ary = new int[4][2];
访问:
访问某个位置的元素,通过下标访问
*/