近期面试题总结【三】

----Java

--基础

  • 我能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗?

    不行,你不能在没有强制类型转换的前提下将一个 double 值赋值给 long 类型的变量,因为 double 类型的范围比 long 类型更广,所以必须要进行强制转换。

  • 3*0.1 == 0.3 将会返回什么?true 还是 false?

    false,因为有些浮点数不能完全精确的表示出来。

  • int 和 Integer 哪个会占用更多的内存?

    Integer 对象会占用更多的内存。Integer 是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少。

  • 我们能在 Switch 中使用 String 吗?

    从 Java 7 开始,我们可以在 switch case 中使用字符串,但这仅仅是一个语法糖。内部实现在 switch 中使用字符串的 hash code。

  • Java 中的构造器链是什么?

    当你从一个构造器中调用另一个构造器,就是Java 中的构造器链。这种情况只在重载了类的构造器的时候才会出现。

  • ava 中怎样将 bytes 转换为 long 类型?

    String接收bytes的构造器转成String,再Long.parseLong

  • 存在两个类,B 继承 A,C 继承 B,我们能将 B 转换为 C 么?如 C = (C) B;

    可以,向下转型。但是不建议使用,容易出现类型转型异常.

  • JRE、JDK、JVM 及 JIT 之间有什么不同?

    JRE 代表 Java 运行时(Java run-time),是运行 Java 应用所必须的。JDK 代表 Java 开发工具(Java development kit),是 Java 程序的开发工具,如 Java 编译器,它也包含 JRE。JVM 代表 Java 虚拟机(Java virtual machine),它的责任是运行 Java 应用。JIT 代表即时编译(Just In Time compilation),当代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主要的热点代码会被准换为本地代码,这样有利大幅度提高 Java 应用的性能。

  • Java 中堆和栈有什么区别?

    JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。 Difference between stack and heap memory in Java

  • a.hashCode() 有什么用?与 a.equals(b) 有什么关系?

    hashCode() 方法是相应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的 hash code。

  • 重写和重载的区别
  • group by order by

--线程

  • 什么是多线程环境下的伪共享(false sharing)?

    伪共享是多线程系统(每个处理器有自己的局部缓存)中一个众所周知的性能问题。伪共享发生在不同处理器的上的线程对变量的修改依赖于相同的缓存行,如下图所示:

    近期面试题总结【三】_第1张图片

    伪共享问题很难被发现,因为线程可能访问完全不同的全局变量,内存中却碰巧在很相近的位置上。如其他诸多的并发问题,避免伪共享的最基本方式是仔细审查代码,根据缓存行来调整你的数据结构。

  • Swing 是线程安全的?

    不是,Swing 不是线程安全的。你不能通过任何线程来更新 Swing 组件,如 JTable、JList 或 JPanel,事实上,它们只能通过 GUI 或 AWT 线程来更新。这就是为什么 Swing 提供 invokeAndWait() 和 invokeLater() 方法来获取其他线程的 GUI 更新请求。这些方法将更新请求放入 AWT 的线程队列中,可以一直等待,也可以通过异步更新直接返回结果。你也可以在参考答案中查看和学习到更详细的内容。

  • Java 中 sleep 方法和 wait 方法的区别?

    虽然两者都是用来暂停当前运行的线程,但是 sleep() 实际上只是短暂停顿,因为它不会释放锁,而 wait() 意味着条件等待,这就是为什么该方法要释放锁,因为只有这样,其他等待的线程才能在满足条件时获取到该锁。

  • Java 中应该使用什么数据类型来代表价格?

    如果不是特别关心内存和性能的话,使用BigDecimal,否则使用预定义精度的 double 类型。

  • Java 中 ++ 操作符是线程安全的吗?

    不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。

  • 你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

    wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。下面是一段标准的使用 wait 和 notify 方法的代码:

     
    // The standard idiom for using the wait method
    synchronized (obj) {
    while (condition does not hold)
    obj.wait(); // (Releases lock, and reacquires on wakeup)
    ... // Perform action appropriate to condition
    }
    

    参见 Effective Java 第 69 条,获取更多关于为什么应该在循环中来调用 wait 方法的内容。

  •  

--内存

  • Java内存模型:
    Java虚拟机规范中将Java运行时数据分为六种。
    1.程序计数器:是一个数据结构,用于保存当前正常执行的程序的内存地址。Java虚拟机的多线程就是通过线程轮流切换并分配处理器时间来实现的,为了线程切换后能恢复到正确的位置,每条线程都需要一个独立的程序计数器,互不影响,该区域为“线程私有”。
    2.Java虚拟机栈:线程私有的,与线程生命周期相同,用于存储局部变量表,操作栈,方法返回值。局部变量表放着基本数据类型,还有对象的引用。
    3.本地方法栈:跟虚拟机栈很像,不过它是为虚拟机使用到的Native方法服务。
    4.Java堆:所有线程共享的一块内存区域,对象实例几乎都在这分配内存。
    5.方法区:各个线程共享的区域,储存虚拟机加载的类信息,常量,静态变量,编译后的代码。
    6.运行时常量池:代表运行时每个class文件中的常量表。包括几种常量:编译时的数字常量、方法或者域的引用。
    友情链接: Java中JVM虚拟机详解
  • 每一次用new分配内存,分配的起地址都是不确定的。所以堆分配的内存是不固定的
  • List、Set、Map 和 Queue 之间的区别
    list 和set 有共同的父类,它们的用法也是一样的,唯一的不一样就是set中不能有相同的元素,list中可以。
    list和set的用途非常广泛 list可以完全代替数组来使用
    map 是独立的合集 它使用键值对的方式来储存数据 键不能有重复的 值可以用有
    map不像上边两种集合那个用的广泛 不过在servlet 和jsp中 map可是绝对的重中之重 页面之间传值全靠map

       List是集合类的接口,子类有ArraryList 和LinkList,通常在Android开发中我们常用的是arrayList,来将数据进行插入和移除。

    其次map也是一个集合映射,不过是键值对的映射,也就是key , value形式,比如当我们需要查询其中的某个对象时,只需要查询其key便能直接获取到他的value(值),就像一个小型的数据库,也有类似于hashmap , Linkedhashmap ,treemap等方法来进一步实现和拓展,并且提高他的性能。

    Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。 Set接口主要实现了两个实现类:

    HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快 
    TreeSet :TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。 
    Set的功能方法 

    Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只 是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素(至于如何判断元素相同则较为负责) 加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。 

    HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。 
    TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。 
    LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
     

     Queue用于模拟"队列"这种数据结构(先进先出 FIFO)。队列的头部保存着队列中存放时间最长的元素,队列的尾部保存着队列中存放时间最短的元素。新元素插入(offer)到队列的尾部,
       访问元素(poll)操作会返回队列头部的元素,队列不允许随机访问队列中的元素。结合生活中常见的排队就会很好理解这个概念
            3.1) PriorityQueue
            PriorityQueue并不是一个比较标准的队列实现,PriorityQueue保存队列元素的顺序并不是按照加入队列的顺序,而是按照队列元素的大小进行重新排序,这点从它的类名也可以
         看出来
            3.2) Deque
            Deque接口代表一个"双端队列",双端队列可以同时从两端来添加、删除元素,因此Deque的实现类既可以当成队列使用、也可以当成栈使用
                3.2.1) ArrayDeque
                是一个基于数组的双端队列,和ArrayList类似,它们的底层都采用一个动态的、可重分配的Object[]数组来存储集合元素,当集合元素超出该数组的容量时,系统会在底层重
           新分配一个Object[]数组来存储集合元素
                3.2.2) LinkedList

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java,面试经验,多线程)