Android面试

牛客网Java练习7

2018-11-21  本文已影响5人  香沙小熊
1.关于对象成员占用内存的说法哪个正确?( )

A 同一个类的对象共用同一段内存
B 同一个类的对象使用不同的内存段,但静态成员共享相同的内存空间
C 对象的方法不占用内存
D 以上都不对
答案 B
静态成员属于类成员,在方法区分配内存,而不是堆。静态变量属于类本身,成员变量属于类的某个实例。


image.png
2.有如下一段程序:
public class Test{
    private static int i=1;
    public int getNext(){
         return i++;
    }
    public static void main(String [] args){
        Test test=new Test();
        Test testObject=new Test();
        test.getNext();
        testObject.getNext();
        System.out.println(testObject.getNext());
    }
}

请问最后打印出来的是什么?()
A 2
B 3
C 4
D 5

答案 B
return i++, 先返回i,然后i+1;
第一次调用getNext()方法时,返回的是1,但此时i=2;
第二次调用 getNext()方法时,返回的是2,但此时i=3;
第三次调用 getNext()方法时,返回的是3,但此时i=4;

3.下面有关java hashmap的说法错误的是?

A HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。
B HashMap 的实现不是同步的,意味着它不是线程安全的
C HashMap通过开放地址法解决哈希冲突
D HashMap中的key-value都是存储在Entry数组中的
答案C

image.png
  1. 开放定址法:线性探测再散列、二次探测再散列、再随机探测再散列;

  2. 再哈希法:换一种哈希函数;

  3. 链地址法 :在数组中冲突元素后面拉一条链路,存储重复的元素;

  4. 建立一个公共溢出区:其实就是建立一个表,存放那些冲突的元素。

什么时候会产生冲突

HashMap中调用 hashCode() 方法来计算hashCode。

由于在Java中两个不同的对象可能有一样的hashCode,所以不同的键可能有一样hashCode,从而导致冲突的产升。

HashMap底层是 数组和链表 的结合体。底层是一个线性数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。数组是 Entry[] 数组,静态内部类。 E ntry就是数组中的元素,每个 Map.Entry 其实就是一个key-value对,它持有一个指向下一个元素的引用 next ,这就构成了链表。所以 很明显是链地址法。

具体过程:

当我们往HashMap中put元素的时候:当程序试图将一个key-value对放入HashMap中时,

1 . 程序首先根据该 key 的 hashCode() 返回值决定该 Entry 的存储位置;

2 . 若 Entry 的存储位置上为 null ,直接存储该对象;若不为空,两个 Entry 的 key 的 hashCode() 返回值相同,那它们的存储位置相同,

3 . 循环遍历链表,如果这两个 Entry 的 key 通过 equals 比较返回 true,新添加 Entry 的 value 将覆盖集合中原有 Entry 的 value,但key不会覆盖;如果这两个 Entry 的 key 通过 equals 比较返回 false,新添加的 Entry 将与集合中原有 Entry 形成 Entry 链,而且新添加的 Entry 位于 Entry 链的头部
HashMap是采用拉链法解决哈希冲突的。

4.下面有关java classloader说法正确的是()?

A ClassLoader就是用来动态加载class文件到内存当中用的
B JVM在判定两个class是否相同时,只用判断类名相同即可,和类加载器无关
C ClassLoader使用的是双亲委托模型来搜索类的
D Java默认提供的三个ClassLoader是Boostrap ClassLoader,Extension ClassLoader,App ClassLoader
E 以上都不正确
答案 A C D

JDK中提供了三个ClassLoader,根据层级从高到低为:

  1. Bootstrap ClassLoader,主要加载JVM自身工作需要的类。
  2. Extension ClassLoader,主要加载%JAVA_HOME%\lib\ext目录下的库类。
  3. 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类,并载入它

5.关于继承和实现说法正确的 是 ? ( )

A 类可以实现多个接口,接口可以继承(或扩展)多个接口
B 类可以实现多个接口,接口不能继承(或扩展)多个接口
C 类和接口都可以实现多个接口
D 类和接口都不可以实现多个接口
答案 A


image.png
6.This调用语句必须是构造函数中的第一个可执行语句。

A 正确
B 错误
答案 B

this()才必须是构造函数中的第一个可执行语句,用this调用语句并不需要。

7.JAVA中,下列语句哪一个正确()

A class中的constructor不可省略
B constructor必须与class同名,但方法不能与class同名
C constructor在一个对象被new时执行
D 一个class只能定义一个constructor
答案 C
答案 C
A 省略构造函数,编译器会自动生成。
D 构造函数可以重载
B 方法是可以和类名同名的,和构造方法唯一的区别就是,构造方法没有返回值

8.在JAVA中,下列哪些是Object类的方法()

A synchronized()
B wait()
C notify()
D notifyAll()
E sleep()

答案 BCD
A synchronized Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
B C D 都是Object类中的方法
notify(): 是唤醒一个正在等待该对象的线程。
notifyAll(): 唤醒所有正在等待该对象的线程。
E sleep 是Thread类中的方法

wait 和 sleep的区别:
wait指线程处于进入等待状态,形象地说明为“等待使用CPU”,此时线程不占用任何资源,不增加时间限制。
sleep指线程被调用时,占着CPU不工作,形象地说明为“占着CPU睡觉”,此时,系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制。

9.在Java线程状态转换时,下列转换不可能发生的有()?

A 初始态->运行态
B 就绪态->运行态
C 阻塞态->运行态
D 运行态->就绪态


image.png
image.png image.png
10.往OuterClass类的代码段中插入内部类声明, 哪一个是错误的:

A

class InnerClass{
public static float func(){return f;}
}

B

abstract class InnerClass{
public abstract float func(){}
}

C

static class InnerClass{
protected static float func(){return f;}
}

D

public class InnerClass{
 static float func(){return f;}
}

答案 ABCD
主要考核了这几个知识点:
1.静态内部类才可以声明静态方法
2.静态方法不可以使用非静态变量
3.抽象方法不可以有函数体

11.以下关于Object类的说法正确的是()

A Java中所有的类都直接或间接继承自Object,无论是否明确的指明,无论其是否是抽象类。
B Java中的接口(interface)也继承了Object类
C 利用“==”比较两个对象时,Java调用继承自Object的equals方法,判断是否相等。
D 如果类的定义中没有重新定义toString()方法,则该类创建的对象无法使用toStrig()方法。
答案 A
A,Object是所有类的直接或者间接父类。
B,接口没有继承Object类。(一旦继承,Object中可以有实例方法的)
C,Object的equals方法,只有一句话,return this==object。这句话说反了。
D,和A一样,都是Object的子类了,肯定有Object的方法:hashCode、equals、toString、clone、notify、notifyall、wait、finalize、getClass

12.静态变量static在不同的实例中地址是否一样?他们储存在什么区域?()

A 地址一样,在堆栈区。
B 地址不一样,在堆栈区。
C 地址一样,在全局区。
D 地址不一样,在全局区。
答案 C

static变量也称作静态变量,静态变量和非静态变量的区别是:
静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

13.transient变量和下面哪一项有关()?

A Serializable
B Cloneable
C Runnable
D Throwable
E Comparable
答案 A

  1. 在序列化的时候,被transient或者static修饰的属性,不可以序列化。
  2. 一个类可以被序列化,那么它的子类也可以被序列化。
  3. 序列化可以实现深复制,而Object中的clone实现的就只是浅复制。
14.下面哪些写法能在 java8 中编译执行()

A dir.listFiles((File f)->f.getName().endsWith(“.Java”));
B dir.listFiles((File f)=>f.getName().endsWith(“.Java”));
C dir.listFiles((_.getName().endsWith(“.Java”)));
D dir.listFiles( f->f.getName().endsWith(“.Java”));
答案 A D
Lanbda表达式的主要作用就是代替匿名内部类的繁琐语法, 它由三部分组成:
(1) 形参列表。形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。
(2) 箭头(→)。必须通过英文中画线和大于符号组成。
(3)代码块。如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号,那么那条语句就不要用花括号表示语句结束。Lambda代码块只有一条return语句,甚至可以省略return关键字。Lambda表达式需要返回值,而它的代码块中仅有一套省略了return的语句。Lambda表达式会自动返回这条语句的值。
由此可见,应该是A和D正确。

15.有关hashMap跟hashTable的区别,说法正确的是?

A HashMap和Hashtable都实现了Map接口
B HashMap是非synchronized,而Hashtable是synchronized
C HashTable使用Enumeration,HashMap使用Iterator
D Hashtable直接使用对象的hashCode,HashMap重新计算hash值,而且用与代替求模
答案 A B C D


image.png
16.在jdk1.8之前,下列哪一种叙述是正确的( )

A abstract修饰符可修饰字段、方法和类
B 抽象方法的body部分必须用一对大括号{ }包住
C 声明抽象方法,大括号可有可无
D 声明抽象方法不可写出大括号
答案 D
abstract修饰符用来修饰类和成员方法

1:用abstract修饰的类表示抽象类,抽象类位于继承树的抽象层,抽象类不能被实例化。

2:用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,但不提供具体的实现。

Abstract是Java中的一个重要关键字,可以用来修饰一个类或者一个方法。 修饰一个方法时,表示该方法只有特征签名(signature),没有具体实现,而是把具体实现留给继承该类的子类。一个类中只要有一个abstract 方法,那么这个类就要被声明为abstract,但是其中可以有非abstract方法。 abstract类可以使得类的设计者能够创建方法的原型,而真正的实现留给使用这个类的人。

17.以下说法错误的是()

A 虚拟机中没有泛型,只有普通类和普通方法
B 所有泛型类的类型参数在编译时都会被擦除
C 创建泛型对象时请指明类型,让编译器尽早的做参数检查
D 泛型的类型擦除机制意味着不能在运行时动态获取List<T>中T的实际类型
答案 D
链接:

1、创建泛型对象的时候,一定要指出类型变量T的具体类型。争取让编译器检查出错误,而不是留给JVM运行的时候抛出类不匹配的异常。
2、JVM如何理解泛型概念 —— 类型擦除。事实上,JVM并不知道泛型,所有的泛型在编译阶段就已经被处理成了普通类和方法。 处理方法很简单,我们叫做类型变量T的擦除(erased) 。 总结:泛型代码与JVM ① 虚拟机中没有泛型,只有普通类和方法。 ② 在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除) ③ 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。 无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字。

/* 通过反射在运行时动态获取List<t>中T的实际类型 */
public class GetGeneric {
    public List<String> list;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException {
          Type t = GetGeneric.class.getDeclaredField("list").getGenericType();  
            if (ParameterizedType.class.isAssignableFrom(t.getClass())) {  
                for (Type t1 : ((ParameterizedType) t).getActualTypeArguments()) {  
                    System.out.print(t1);  
                }  
            } 
    }
}

Java编程思想这样理解泛型的擦除

Java泛型是使用擦除来实现的,这意味着当你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此List<String>和List<Integer>在运行时实际上是相同的类型。这两种类型都被擦除成它们的“原生”类型,即List。

18.下列语句正确的是:

A 形式参数可被字段修饰符修饰
B 形式参数不可以是对象
C 形式参数为方法被调用时真正被传递的参数
D 形式参数可被视为local variable
答案 D
A:形式参数只能被final修饰
B:形式参数可以是对象
C:形式参数被调用时被传递的是实际参数的拷贝
D:local variable:局部变量

19.ArrayList和Vector主要区别是什么?

A Vector与ArrayList一样,也是通过数组实现的,不同的是Vector支持线程的同步
B Vector与ArrayList一样,也是通过数组实现的,不同的是ArrayList支持线程的同步
C Vector是通过链表结构存储数据,ArrayList是通过数组存储数据
D 上述说法都不正确
答案 A
Vector支持线程的同步,也就是内部加锁的
但是效率低,因此在新版jdk中加入线程不安全的Arraylist

20.关于OutOfMemoryError,下面说法正确的是()?

A java.lang.OutOfMemoryError: PermGen space 增加-XX:MaxPermSize这个参数的值的话,这个问题通常会得到解决。
B java.lang.OutOfMemoryError: Requested array size exceeds VM limit当你正准备创建一个超过虚拟机允许的大小的数组时,这条错误将会出现
C java.lang.OutOfMemoryError: Java heap space 一般情况下解决这个问题最快的方法就是通过-Xmx参数来增加堆的大小
D java.lang.OutOfMemoryError: nativeGetNewTLA这个异常只有在jRockit虚拟机时才会碰到

答案 A B C

java.lang.OutOfMemoryError: PermGen space
查了一下为"永久代"内存大小不足,“永久代”的解释应该为JVM中的方法区,主要用于存储类信息,常量,静态变量,即时编译器编译后代码等。本错误仅限于Hotspot虚拟机,本区进行垃圾回收很少,不够直接加大简单粗暴。

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
直接翻译报错信息:数组过长导致堆内存溢出,加大堆内存或者减少数组长度。

java.lang.OutOfMemoryError: Java heap space
堆内存不足,直接增大堆内存。

上一篇下一篇

猜你喜欢

热点阅读