笔试题和算法题1

  1. HashMap如何解决哈希冲突?

HashMap是由数组+链表组成的,jdk1.8后加入了红黑树。它使用链地址法来解决哈希冲突,这样我们可以将具有相同哈希值的对象组织成一个链表放在hash值所对应的bucket下

  1. java中数组复制效率对比

在Java语言中,有几种数组复制方法,包括System.arraycopy、clone、Arrays.copyOf和for循环。其中,System.arraycopy的效率最高,其次是clone,然后是Arrays.copyOf,最后是for循环。

  1. java中二维数组创建的正确语句

float f [][] = new float[6][6]

float []f[] = new float[6][6]

float [][]f = new float[6][6]

float [][]f = new float[6][]

  1. 如何保证在多线程环境下保证线程顺序执行又保证线程安全

在多线程环境下,可以使用多种方法来保证线程顺序执行并保证线程安全。例如,可以使用Thread类中的join方法来保证多个线程按指定的顺序执行。此外,还可以使用CountDownLatch、CyclicBarrier、Semaphore等并发工具类来实现线程的同步和顺序执行。

  1. join方法:join方法是Thread类中的一个方法,它可以让当前线程等待调用join方法的线程执行完成后再继续执行。例如,如果线程A调用了线程B的join方法,那么线程A会等待线程B执行完成后再继续执行。

  2. CountDownLatch:CountDownLatch是一个并发工具类,它允许一个或多个线程等待其他线程完成操作。它的构造函数接受一个int类型的参数,表示需要等待的线程数量。当一个线程完成操作时,它可以调用CountDownLatch的countDown方法来减少计数器的值。其他线程可以调用CountDownLatch的await方法来等待计数器减为0。

  3. CyclicBarrier:CyclicBarrier也是一个并发工具类,它允许一组线程互相等待,直到所有线程都到达某个屏障点。它的构造函数接受一个int类型的参数,表示需要等待的线程数量。当一个线程到达屏障点时,它会调用CyclicBarrier的await方法来等待其他线程。当所有线程都到达屏障点时,屏障将打开,所有线程都将继续执行。

  4. Semaphore:Semaphore是一个计数信号量,它可以用来控制对共享资源的访问。它的构造函数接受一个int类型的参数,表示允许同时访问共享资源的最大线程数量。当一个线程需要访问共享资源时,它可以调用Semaphore的acquire方法来获取许可。如果当前没有可用的许可,那么该线程将阻塞,直到有可用的许可为止。当一个线程完成对共享资源的访问后,它可以调用Semaphore的release方法来释放许可。

这些方法都可以用来保证多个线程按指定顺序执行并保证线程安全。

  1. 针对jdk1.7,不属于JVM堆内存中的区域,

java7,字符串常量池从方法区移到堆中。java8 整个常量池从方法区中移除。方法区使用元空间(MetaSpace)实现 。

  1. 关于jvm的一些看法,,

    1. JVM大体分为堆、栈、方法区和程序计数器四个部分。其中堆和方法区对线程共享,栈和程序计数器对线程隔离。
    2. 堆:存放数组和对象实例 ,- 栈:存放局部变量和数据类型 ,- 方法区:存放静态变量、常量、类信息和代码,,程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行 到了第几行,是线程隔离的 ,原则上讲,所有的对象都是在堆区上分配内存,是线程之间共享的 , Java方法执行内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的 ,
  2. TreeSet使用二叉树对元素进行排序

  3. 读写锁的一些知识:

CopyOnWriteArrayList适用于写少读多的并发场景 ,ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥, 读与读之间可以并发执行。在读多写少的情况下可以提高效率 ,ConcurrentHashMap是同步的HashMap,读写都加锁,volatile只保证多线程操作的可见性,不保证原子性

  1. Servlet中HttpServletRequest.getParameter获取的参数

由客户端浏览器和web容器配置共同决定编码。

  1. 成员内部类前面可以修饰public,protected,private.

  2. 在接口interface主体内声明常量的public static int answer = 42;

  3. 在java7中能做switch()参数的类型:

    1. int 型
    2. 枚举类型
    3. 字符串类型(String ) jdk7以后新增
    4. short
    5. char
    6. long

    不能作为switch的类型:

    1. float
    2. double
    3. boolean
  4. jre判断程序是否执行结束的标准:

    所有前台线程执行完毕

    后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。 前台线程:是指接受后台线程服务的线程,其实前台后台线程是联系在一起,就像傀儡和幕后操纵者一样的关系。傀儡是前台线程、幕后操纵者是后台线程。由前台线程创建的线程默认也是前台线程。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。

  5. //以下代码输出什么  null
    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();
        }
    }
    

(1) 父类静态代码块(包括静态初始化块,静态属性,但不包括静态方法)

(2) 子类静态代码块(包括静态初始化块,静态属性,但不包括静态方法 )

(3) 父类非静态代码块( 包括非静态初始化块,非静态属性 )

(4) 父类构造函数

(5) 子类非静态代码块 ( 包括非静态初始化块,非静态属性 )

(6) 子类构造函数

​ 其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)

2.其次,需要理解子类覆盖父类方法的问题,也就是方法重写实现多态问题。

​ Base b = new Sub();它为多态的一种表现形式,声明是Base,实现是Sub类, 理解为 b 编译时表现为Base类特性,运行时表现为Sub类特性。

​ 当子类覆盖了父类的方法后,意思是父类的方法已经被重写,题中 父类初始化调用的方法为子类实现的方法,子类实现的方法中调用的baseName为子类中的私有属性。

​ 由1.可知,此时只执行到步骤4.,子类非静态代码块和初始化步骤还没有到,子类中的baseName还没有被初始化。所以此时 baseName为空。 所以为null。