美文网首页Android面试
牛客网Java练习7

牛客网Java练习7

作者: 香沙小熊 | 来源:发表于2018-11-21 16:45 被阅读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
    堆内存不足,直接增大堆内存。

    相关文章

      网友评论

        本文标题:牛客网Java练习7

        本文链接:https://www.haomeiwen.com/subject/extfqqtx.html