首页 技术 正文
技术 2022年11月22日
0 收藏 484 点赞 5,095 浏览 21309 个字

                                题目目录

Java基础

1.JDK1.8新特性?

2.面向对象和面向过程的区别?

3.什么是值传递和引用传递?

4.什么是不可变对象?

5.讲讲类的实例化顺序?

6.java 创建对象的几种方式

7.Java访问修饰符的作用域

8.switch中能否使用string作为参数?

9.switch中能否作用在byte,long上?

10.什么是自动拆装箱?

11.如何正确的退出多层嵌套循环?

继承

1.Java支持多继承么?

2.父类的静态方法能否被子类重写?

3.继承的好处和坏处?

接口抽象类

1.接口的意义?

2.抽象类的意义?

3.抽 象 的 (abstract) 方 法 是 否 可 同 时 是 静 态 的 (static), 是 否 可 同 时 是 本 地 方 法(native)?

4.抽象类和接口区别?

5.Java中接口可不可以继承一般类,为什么?

6.重载与重写区别?

7.final有哪些用法?

多态

1.多态的好处和弊端?

2.代码中如何实现多态?

3.Java 中实现多态的机制是什么?

内部类Lambda

1.内部类的作用?

2.一个java文件内部可以有类?(非内部类)

3.Lambda的使用前提是什么?

4.Lambda与匿名内部类区别?

static关键字

1.是否可以在static环境中访问非static变量?

2.static都有哪些用法?

3.静态变量和实例变量的区别?

4.static特点?

数据类型

1.String s1=”ab”, String s2=”a”+”b”, String s3=”a”, String s4=”b”, s5=s3+s4请问s5==s2返回什么?

2.3*0.1==0.3返回值是什么?

3.基本数据类型的默认值?基本数据类型所占的字节以及封装他们的类?

4.String属于那个类,以及常用的方法?

5.String, StringBuffer和StringBuilder区别?

异常类

1.error和exception有什么区别?

2.运行时异常和一般异常有何不同?

3.Java中异常处理机制的原理?

4.你平时在项目中是怎样对异常进行处理的?

5.throw和throws有什么区别?

6.异常处理的时候,finally代码块的重要性是什么?

7.请列出 5 个运行时异常?

8.try catch finally,try里有return,finally还执行么?

集合

1、List、Map、Set三个接口,存取元素时,各有什么特点?

2、ArrayList和LinkedList的底层实现原理?他们为什么线程不安全?在多线程并发操作下,我们应该用什么替代?

3、HashMap和HashTable有什么区别?其底层实现是什么?CurrentHashMap的锁机制又是如何?如果想将一个Map变为有序的,该如何实现?

4.什么是迭代器(Iterator)?

5.Arraylist 与 LinkedList 区别?

6.Arraylist 与 LinkedList 应用场景?

7.Collection 和 Collections的区别?

8.为何Map接口不继承Collection接口?

9.当两个对象的hashcode相同会发生什么?

10.HashMap和Hashtable有什么区别?

11.List 和 Set 区别?

12.Set和List对比?

13.当两个对象的hashcode相同会发生什么?

14.如果两个键的hashcode相同,你如何获取值对象?

15.有没有可能两个不相等的对象有相同的hashcode?

16.HashMap、LinkedHashMap、TreeMap的区别?

17.HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。

18.==和 equals hashCode 的区别?

19.自然排序Comparble和比较器排序Comparator的异同点?

泛型

1.为什么使用泛型?

2.泛型用在什么地方?

3.如何使用泛型类?

1.什么是二叉树?

2.什么是二叉查找树?

3.什么是平衡二叉树?

序列化

1.什么是 Java 序列化?

2.如何实现 Java 序列化?

3.Java 序列话中,如果有些字段不想进行序列化怎么办?

4.对象操作流是字符流还是字节流?

5.如何在读写文件时指定字符集?

6.字符缓冲流特有方法?

7.为什么使用对象流?

多线程

1.什么是线程?

2.线程和进程有什么区别?

3.如何在Java中实现线程?

4.用Runnable还是Thread?

5.Thread 类中的start() 和 run() 方法有什么区别?

6.Java中Runnable和Callable有什么不同?

7.Java内存模型是什么?

8.Java中的volatile 变量是什么?

9.什么是线程安全?Vector是一个线程安全类吗?

10.Java中如何停止一个线程?

11.Java中notify 和 notifyAll有什么区别?

12. 什么是线程池? 为什么要使用它?

13.如何写代码来解决生产者消费者问题?

14.Java多线程中的死锁?

15.Java中synchronized 和 ReentrantLock 有什么不同?

16.详谈Synchronized?

17.在Java中Lock接口与synchronized块的区别是什么?

18.synchronized 的原理是什么?有什么不足?

19.关于成员变量和局部变量?

20. 如果你提交任务时,线程池队列已满。会时发会生什么?

21.volatile关键字的作用是?

22.守护线程和非守护线程有什么区别?

23.线程的生命周期?

24.wait和sleep,notify()锁方面区别?

25.什么情况下会出现线程安全问题?

26.Java中规定了线程有哪几种状态?

反射

1.Java反射机制的作用?

2.什么是反射机制?

3.哪里用到反射机制?

4.反射机制的优缺点?

5.反射中,Class.forName 和 ClassLoader 区别

                                题目答案

Java基础

1.JDK1.8新特性?

提供lambda表达式极大地减少了代码的冗余; 在接口中可以使用default和static关键字来修饰接口中的普通方法; 提供新的API LocalDate | LocalTime | LocalDateTime (1)Java.util.Date和SimpleDateFormatter线程上都不安全,而LocalDate和LocalTime和 String一样都是不可改变类,线程上比较安全,还不能修改; (2)Java.util.Date月份从0开始,12月是11,而java.time.LocalDate月份和星期都改成了 enum, 就不可能出错了;

2.面向对象和面向过程的区别?

面向过程

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源。比如,单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展。

面向对象

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护。

缺点:性能比面向过程低。

3.什么是值传递和引用传递?

值传递,是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。

引用传递,一般是对于对象型变量而言的,传递的是该对象地址的一个副本,并不是原对象本身。

一般认为,Java 内的传递都是值传递,Java 中实例对象的传递是引用传递。

4.什么是不可变对象

不可变对象指对象一旦被创建,状态就不能再改变。任何修改都会创建一个新的对象,如 String、Integer及其它包装类。

5.讲讲类的实例化顺序?

初始化顺序如下

父类静态变量

父类静态代码块

子类静态变量、

子类静态代码块

父类非静态变量(父类实例成员变量)

父类构造函数

子类非静态变量(子类实例成员变量)

子类构造函数

6.java 创建对象的几种方式

采用new

通过反射

采用clone

通过序列化机制

前2者都需要显式地调用构造方法。造成耦合性最高的恰好是第一种,因此你发现无论什么框架,只要涉及到解耦必先减少new的使用

7.Java访问修饰符的作用域

作用域 当前类 同包 子类 其它

public Y Y Y Y

protected Y Y Y N

default Y Y N N

private Y N N N

8.switch中能否使用string作为参数?

在jdk1.7之前,switch只能支持byte,short,char,int或者其他对应的封装类以及Enum类型.jdk1.7之后开始支持String

9.switch中能否作用在byte,long上?

可以用在byte上,不能用在long上

10.什么是自动拆装箱?

自动装箱和拆箱,就是基本类型和引用类型之间的转换。

把基本数据类型转换成包装类的过程就是打包装,为装箱。

把包装类转换成基本数据类型的过程就是拆包装,为拆箱。

13.如何正确的退出多层嵌套循环?

使用标号和break;

继承

1.Java支持多继承么?

Java类中不支持多继承,但是可以多实现,所以接口的扩展性比较好,实际开发中尽量避免继承的使用

2.父类的静态方法能否被子类重写**

不能。重写只适用于实例方法,不能用于静态方法,而子类当中含有和父类相同签名的静态方法,我们一般称之为隐藏。

3.继承的好处和坏处

好处:1、子类能自动继承父类的对象 2、创建子类的对象时,无须创建父类的对象 坏处:1、破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性。 2、支持扩展,但是往往以增强系统结构的复杂度为代价 3、不支持动态继承。在运行时,子类无法选择不同的父类 4、子类不能改变父类的接口

接口抽象类

1.接口的意义

规范,扩展,回调。

2.抽象类的意义

为其他子类提供一个公共的类型

封装子类中重复定义的内容

定义抽象方法,子类虽然有不同的实现,但是定义时一致的

3.抽 象 的 (abstract) 方 法 是 否 可 同 时 是 静 态 的 (static), 是 否 可 同 时 是 本 地 方 法(native)

abstract关键字不能同时与static或private或final同时修饰一个方法;

4.抽象类和接口区别?
  1. 语法区别:

    1. 抽象类可以有构造方法,接口不能有构造方法

    2. 抽象类中可以有普通成员变量,接口中没有普通成员变量;

    3. 抽象类中可以有非抽象的方法,接口中的方法都必须是抽象的;

    4. 抽象类中的方法可以是public,protected类型,接口中的方法只能是public类型的,切 默认为public abstract类型;

    5. 抽象类中可以有静态方法,接口中不能有静态方法;

    6. 抽象类中的静态变量访问类型可以是任意的,但接口中的静态变量只能是public static final 类型。

    7. .一个类可以实现多个接口,但一个类只能继承一个抽象类;

  2. 应用区别:

    1. 接口更多是在系统架构方面发挥作用,主要用于定义模块之间的通信契约;而抽象类在代码方法 发挥作用,可以使用代码块的重用;

5.Java中接口可不可以继承一般类,为什么?

不可以因为接口中只能出现3种成员:

  1. 公共的静态常量

  2. 公共的抽象方法

  3. 静态内部类

而一个类中,就算什么都不写,也必须带一个构造方法,在extends时就会被子类继承,如果是接口也会 继承这个构造方法,很明显构造方法不在上面三项之列 而如果类中有一般的方法和成员变量,也会被子类全部继承,这些更不能出现在接口中了,所以接口是绝 对不可能继承一个类的

6.重载与重写区别

override(重写)

   1、方法名、参数、返回值相同。

   2、子类方法不能缩小父类方法的访问权限。

   3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。

   4、存在于父类和子类之间。

   5、被final修饰的方法,不能被重写。

 overload(重载)

  1、参数类型、个数、顺序至少有一个不相同。

  2、不能重载只有返回值不同的方法名。

  3、存在于父类和子类、同类中。

7.final有哪些用法?

1.被final修饰的类不可以被继承

2.被final修饰的方法不可以被重写

3.被final修饰的变量不可以被改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。

注:修饰变量, final 数据类型 变量名=数据值; 如果该变量是基本数据类型,则值不能修改,如果该变量是引用数据类型,则地址值不能改(既只能new一次);

4.被final修饰的方法,JVM会尝试将其内联,以提高运行效率

5.被final修饰的常量,在编译阶段会存入常量池中。

回答出编译器对final域要遵守的两个重排序规则更好:

1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

2.初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

多态

1.多态的好处和弊端

许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。即父类型的引用指向子类型的对象。

主要有以下优点:

可替换性:多态对已存在代码具有可替换性

可扩充性:增加新的子类不影响已经存在的类结构

更加灵活

弊端:

不能使用子类的特有内容

2.代码中如何实现多态

实现多态主要有以下三种方式:

  1. 接口实现

  2. 继承父类重写方法

  3. 同一类中进行方法重载

3.Java 中实现多态的机制是什么?

父类对象指向子类引用

内部类Lambda

1.内部类的作用?

内部类可以有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立.在单个外围类当中,可以让多个内部类以不同的方式实现同一接口,或者继承同一个类.创建内部类对象的时刻不依赖于外部类对象的创建。

内部类提供了更好的封装,除了该外围类,其他类都不能访问。

2.一个java文件内部可以有类?(非内部类)

只能有一个public公共类,但是可以有多个default修饰的类。

3.Lambda的使用前提是什么?

当需要一个接口的实现类对象,且接口中有且仅有一个抽象方法的时候,可以使用lambda完成这个实现类要做的事情;(替代匿名内部类)

4.Lambda与匿名内部类区别

lambda表达式编译后并不会生成.class文件,而匿名内部类编译后会产生单独的class文件;

匿名内部类可以用在类,抽象类,接口中,而lambda表达式只能用在有且仅有一个抽象方法的接口中;

static关键字

1.是否可以在static环境中访问非static变量?

static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。

2.static都有哪些用法?

被static所修饰的变量/方法都属于类的静态资源,类实例所共享。

static也用于静态块,多用于初始化操作:

此外static也多用于修饰内部类,此时称之为静态内部类。

3.静态变量和实例变量的区别?

静态变量存储在方法区,属于类所有。实例变量存储在堆当中,其引用存在当前线程栈。

4.static特点

如果修饰构造代码块,仅在类第一次加载的时候,执行一次;

如果修饰成员变量,这个变量的值属于类;可以被所有的对象共享;

如果修饰成员方法,在方法中不能使用this,super;

静态的内容优先于对象存在!

数据类型

1.String s1=”ab”, String s2=”a”+”b”, String s3=”a”, String s4=”b”, s5=s3+s4请问s5==s2返回什么?

返回false。在编译过程中,编译器会将s2直接优化为”ab”,会将其放置在常量池当中,s5则是被创建在堆区,相当于s5=new String(“ab”);

2.3*0.1==0.3返回值是什么

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

3.基本数据类型的默认值?基本数据类型所占的字节以及封装他们的类?
  1. 默认值

    1. byte、short、int、long的默认值为0

    2. float、double默认值为0.0

    3. char默认值为空

    4. boolean默认值为false

  2. 所占字节

    1. byte 1个字节–Byte

    2. short 2个字节–Short

    3. char 2个字节–Character

    4. int 4个字节–Integer

    5. long 8个字节–Long

    6. float 4个字节–Float

    7. double 8个字节–Double

4.String属于那个类,以及常用的方法?
  1. .java.lang.string

  2. substring(),indexOf(),concat(),endswith(),length(),replace()

5.String, StringBuffer和StringBuilder区别

String的值是不可改变的,这就导致每次对String的操作都会生成新的String对象,不禁效率底下, 而且浪费大量的内存空间;

StringBuilder是可变类,任何对他指向的字符串的操作都不会产生新的对 象,但单线程不安全;

StringBuffer底层方法使用了synchronized关键字,线程比较安全,但效率 较StringBuilder慢

异常相关

1.error和exception有什么区别

error表示系统级的错误,是java运行环境内部错误或者硬件问题,不能指望程序来处理这样的问题,除了退出运行外别无选择,它是Java虚拟机抛出的。

exception 表示程序需要捕捉、需要处理的异常,是由与程序设计的不完善而出现的问题,程序必须处理的问题

2.运行时异常和一般异常有何不同

Java提供了两类主要的异常:runtimeException和checkedException

一般异常(checkedException)主要是指IO异常、SQL异常等。对于这种异常,JVM要求我们必须对其进行cathc处理,所以,面对这种异常,不管我们是否愿意,都是要写一大堆的catch块去处理可能出现的异常。

运行时异常(runtimeException)我们一般不处理,当出现这类异常的时候程序会由虚拟机接管。比如,我们从来没有去处理过NullPointerException,而且这个异常还是最常见的异常之一。

出现运行时异常的时候,程序会将异常一直向上抛,一直抛到遇到处理代码,如果没有catch块进行处理,到了最上层,如果是多线程就有Thread.run()抛出,如果不是多线程那么就由main.run()抛出。抛出之后,如果是线程,那么该线程也就终止了,如果是主程序,那么该程序也就终止了。

其实运行时异常的也是继承自Exception,也可以用catch块对其处理,只是我们一般不处理罢了,也就是说,如果不对运行时异常进行catch处理,那么结果不是线程退出就是主程序终止。

如果不想终止,那么我们就必须捕获所有可能出现的运行时异常。如果程序中出现了异常数据,但是它不影响下面的程序执行,那么我们就该在catch块里面将异常数据舍弃,然后记录日志。如果,它影响到了下面的程序运行,那么还是程序退出比较好些。

3.Java中异常处理机制的原理

Java通过面向对象的方式对异常进行处理,Java把异常按照不同的类型进行分类,并提供了良好的接口。当一个方法出现异常后就会抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并对异常进行处理。Java的异常处理是通过5个关键词来实现的:try catch throw throws finally。

一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws),我们可以通过它的类型来捕捉它,或最后由缺省处理器来处理它(finally)。

try:用来指定一块预防所有异常的程序

catch:紧跟在try后面,用来捕获异常

throw:用来明确的抛出一个异常

throws:用来标明一个成员函数可能抛出的各种异常

finally:确保一段代码无论发生什么异常都会被执行的一段代码。

4.你平时在项目中是怎样对异常进行处理的。

1)尽量避免出现runtimeException 。例如对于可能出现空指针的代码,带使用对象之前一定要判断一下该对象是否为空,必要的时候对runtimeException

也进行try catch处理。

(2)进行try catch处理的时候要在catch代码块中对异常信息进行记录,通过调用异常类的相关方法获取到异常的相关信息,返回到web端,不仅要给用户良好的用户体验,也要能帮助程序员良好的定位异常出现的位置及原因。例如,以前做的一个项目,程序遇到异常页面会显示一个图片告诉用户哪些操作导致程序出现了什么异常,同时图片上有一个按钮用来点击展示异常的详细信息给程序员看的。

5.throw和throws有什么区别?

throw关键字用来在程序中明确的抛出异常,相反,throws语句用来表明方法不能处理的异常。每一个方法都必须要指定哪些异常不能处理,所以方法的调用者才能够确保处理可能发生的异常,多个异常是用逗号分隔的。

6.异常处理的时候,finally代码块的重要性是什么?

无论是否抛出异常,finally代码块总是会被执行。就算是没有catch语句同时又抛出异常的情况下,finally代码块仍然会被执行。最后要说的是,finally代码块主要用来释放资源,比如:I/O缓冲区,数据库连接。

7.请列出 5 个运行时异常?

NullPointerException 空指针

IndexOutOfBoundsException 索引越界

ClassCastException 类型转换异常

ArrayStoreException 当你试图将错误类型的对象存储到一个对象数组时抛出的异常

BufferOverflowException 写入的长度超出了允许的长度

IllegalArgumentException 方法的参数无效

NoClassDefFoundException – JAVA运行时系统找不到所引用的类

8.try catch finally,try里有return,finally还执行么?

1、finally语句总会执行

即使try里包含continue,break,return,try块结束后,finally块也会执行

2、如果try、catch中有return语句,finally中没有return,那么在finally中修改除包装类型和静态变量、全局变量以外的数据都不会对try、catch中返回的变量有任何的影响(包装类型、静态变量会改变、全局变量)

3、尽量不要在finally中使用return语句,如果使用的话,会忽略try、catch中的返回语句,也会忽略try、catch中的异常,屏蔽了错误的发生。

4、finally中避免再次抛出异常,一旦finally中发生异常,代码执行将会抛出finally中的异常信息,try、catch中的异常将被忽略

集合部分

1、List、Map、Set三个接口,存取元素时,各有什么特点?

1)Set集合的add有一个boolean类型的返回值,当集合中没有某个元素时,则可以成功加入该 元素,返回结果为true;当集合中存在与某个元素equals方法相等 的元素时,则无法加入该元素, 取元素时只能用Iterator接口取得所有元素,在逐一遍历各个元素; (2)List表示有先后顺序的集合,调用add()方法,指定当前对象在集合中的存放位置;一个对象可 以被反复存进集合中;每调用一次add()方法,该对象就会被插入集合中一次,其实,并不是把对 象本身存进了集合中,而是在集合中使用一个索引变量指向了该对象,当一个对象被add多次时, 即有多个索引指向了这个对象。List去元素时可以使用Iterator取出所有元素,在逐一遍历,还可 以使用get(int index)获取指定下表的元素; (3)Map是双列元素的集合,调用put(key,value),要存储一对key/value,不能存储重复的key, 这个是根据eauals来判断;取元素时用get(key)来获取key所对 应的value,另外还可以获取 全部key,全部value

2、ArrayList和LinkedList的底层实现原理?他们为什么线程不安全?在多线程并发操作下,我们应该用什么替代?

1.ArrayList底层通过数组实现,ArrayList允许按序号索引元素,而插入元素需要对数组进行移位等内存操作,所以索引快插入较慢;(扩容方式)一旦我们实例化了ArrayList 无参构造函数默认数组长度为10。add方法底层如 果增加的元素超过了10个,那么ArrayList底层会生成一个新的数组,长度为原来数组长度的1.5倍+1,然后将原数组内容复制到新数组中,并且后续加的内容都会放到新数组中。当新数组无法容纳增加元素时,重复该过程;

2.LinkedList底层通过双向链表实现,取元素时需要进行前项或后项的遍历,插入元素时只需要记录本项的前后 项即可,所以插入快查询慢;

3.ArrayList和LinkedList底层方法都没有加synchronized关键词,多线程访问时会出现多个线程先后更改数据造成得到的数据是脏数据;多线程并发操作下使用Vector来代替,Vector底层也是数组,但底层方法都加synchronized关键字使线程安全,效率较ArrayList差;

3、HashMap和HashTable有什么区别?其底层实现是什么?CurrentHashMap的锁机制又是如何?如果想将一个Map变为有序的,该如何实现?

1.区别: (1)HashMap没有实现synchronized线程非安全,HashTable实现了synchronized线程安全; (2)HashMap允许key和value为null,而HashTable不允许

2.底层原理:数组+链表实现

3.ConcurrentHashMap锁分段技术:HashTable效率低下的原因,是因为所访问HashTable的线程都必须竞争同一把锁,那假如容器中有多把锁,每一把锁用于锁住容器中的一部分数据,那么当多线程访问容器中不同的数据时,线程间就不会存在锁竞争,从而提高并发访问率;ConcurrentHashMap使用的就是锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个数据时,其他段的数据也能被其他线程访问;

4.实现TreeMap

4.什么是迭代器(Iterator)?

Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素,但是不可以直接调用集合的remove(Object Obj)删除,可以通过迭代器的remove()方法删除

5.Arraylist 与 LinkedList 区别

Arraylist:

优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。

缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

LinkedList:

优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景

缺点:因为LinkedList要移动指针,所以查询操作性能比较低。

6.Arraylist 与 LinkedList 应用场景?

当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

7.Collection 和 Collections的区别

Collection是集合类的上级接口,继承与他的接口主要有Set 和List.Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作(带s的基本都是工具类,如Arrays)

8.为何Map接口不继承Collection接口?

尽管Map接口和它的实现也是集合框架的一部分,但Map不是集合,集合也不是Map。因此,Map继承Collection毫无意义,反之亦然。

如果Map继承Collection接口,那么元素去哪儿?Map包含key-value对,它提供抽取key或value列表集合的方法,但是它不适合“一组对象”规范。

9.当两个对象的hashcode相同会发生什么?

因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。

10.HashMap和Hashtable有什么区别?

1、HashMap是非线程安全的,HashTable是线程安全的。

2、HashMap的键和值都允许有null值存在,而HashTable则不行。

3、因为线程安全的问题,HashMap效率比HashTable的要高。

4、Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。

一般现在不建议用HashTable, ①是HashTable是遗留类,内部实现很多没优化和冗余。②即使在多线程环境下,现在也有同步的ConcurrentHashMap替代,没有必要因为是多线程而用HashTable。

11.List 和 Set 区别

List,Set都是继承自Collection接口

List特点:元素有放入顺序,元素可重复

Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉

(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)

12.Set和List对比

Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

13.当两个对象的hashcode相同会发生什么?

因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。

14.如果两个键的hashcode相同,你如何获取值对象?

当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。

15.有没有可能两个不相等的对象有相同的hashcode

有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。如果两个对象相等,必须有相同的hashcode 值,反之不成立。

16.HashMap、LinkedHashMap、TreeMap的区别。**

1、HashMap是根据键的hashcode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,取得的数据完全是随机的

2、LinkedHashMap保存了记录的插入顺序,在使用Iterator进行遍历的时候,先得到的肯定是先插入的数据,可以在构造时带参数,按照应用次数来进行排序

3、TreeMap实现SortMap接口,能够把它保存的记录根据键排序。默认的是升序排序,也可以指定排序的比较器,进行遍历的时候得到的是排序过的记录。

17.HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。**

1、HashMap是java数据结构中两大结构数组和链表的组合。HashMap底层数组,数组中的每一项又是一个链表。程序会先根据key的hashcode()方法返回值决定该Entry在数组中的

存储位置,如果该位置上没有元素,就会将元素放置在此位置上,如果两个Entry的key相同,会调用equals,返回值是true则覆盖原来的value值,返回false则会形成Entry链,位于头部。

2、ArrrayList的底层实现是数组,在执行add操作时,会先检查数组 大小是否可以容纳新的元素,如果不够就会进行扩容。然后会将原来的数据拷贝到新的数组中。

3、LinkedList底层是一个链表,其实现增删改查和数据结构中的操作完全相同,而且插入是有序的。

4、LinkedHashMap的底层结构式是双链表,其他的逻辑处理与HashMap一致,同样没有锁保护,多线程使用时存在风险。

5、ConcurrentHashMap是segment数组结构和HashEntry数组结构组成的,segment在ConcurrentHashMap中充当锁的角色,HashEntry用于存储键值对数据。segment的结构是数组和链表,一个segment中有一个HashEntry,每个HashEntry是一个链表结构的元素。对HashEntry中的数据进行修改时,需要先获得它所对应的segment锁。每个ConcurrentHashMap默认有16个segment。

18.==和 equals hashCode 的区别?

基本数据类型: ==比较的是内容 引用数据类型: ==比的是地址值,equals默认比地址值,重写按照规则比较,hashCode

19.自然排序Comparble和比较器排序Comparator的异同点?

相同点:

返回值的规则:

  • 如果返回值为负数,表示当前存入的元素是较小值,存左边

  • 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存

  • 如果返回值为正数,表示当前存入的元素是较大值,存右边

不同点:

1.用到的接口不同

  • 自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序

  • 比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序

2.使用场景不同

  • 自然排序能满足大部分情况

  • 存储没有修改权限的类时可以使用

泛型

1.为什么使用泛型?

它提供了编译时类型安全检测机制,把运行时期的问题提前到了编译期间

避免了强制类型转换

2.泛型用在什么地方?

类,方法,接口

3.如何使用泛型类?

创建泛型类对象时,必须要给这个泛型确定具体的数据类型

1.什么是二叉树?

任意节点的子节点不超过2

2.什么是二叉查找树?

每个节点最多有两个子节点,左边比当前节点小,右边比当前节点大

3.什么是平衡二叉树?

二叉树左右子树的树高差不超过1,任意节点的左右子树都是平衡二叉树

通过左旋右旋保持树的平衡

序列化

1.什么是 Java 序列化?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。

可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。

序列化是为了解决在对对象流进行读写操作时所引发的问题。

反序列化的过程,则是和序列化相反的过程。

另外,我们不能将序列化局限在 Java 对象转换成二进制数组,例如说,我们将一个 Java 对象,转换成 JSON 字符串,或者 XML 字符串,这也可以理解为是序列化。

2.如何实现 Java 序列化?

将需要被序列化的类,实现 Serializable 接口,该接口没有需要实现的方法,implements Serializable 只是为了标注该对象是可被序列化的。

序列化

然后,使用一个输出流(如:FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象

接着,使用 ObjectOutputStream 对象的 #writeObject(Object obj) 方法,就可以将参数为 obj 的对象写出(即保存其状态)。

反序列化

要恢复的话则用输入流。

3.Java 序列话中,如果有些字段不想进行序列化怎么办?

对于不想进行序列化的变量,使用 transient 关键字修饰。

当对象被序列化时,阻止实例中那些用此关键字修饰的的变量序列化。

当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

transient 只能修饰变量,不能修饰类和方法。

4.对象操作流是字符流还是字节流?

字节流

5.如何在读写文件时指定字符集?

jdk11之前:

使用转换流InputStreamReader(输入转换流)字节转换字符桥梁/OutputStreamWriter(输出转换流)字符转字节桥梁

jdk11之后

直接使用FileReader指定

6.字符缓冲流特有方法?

readLine():读取一整行,到达尾处为null

newLine():跨平台换行

7.为什么使用对象流?

在开发中,经常需要将对象的信息保存到磁盘中,如果使用前面所学的知识来实现,会非常的繁琐。使用对象流就非常的方便

对象操作流可以将对象以字节的形式写到本地文件中,直接打开是看不懂的,需要时可以再次用对象操作流读到内存中

多线程

1.什么是线程?

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。线程是进程的一部分,是进程中的单个控制流,是一条执行路径

2.线程和进程有什么区别?

线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。

3.如何在Java中实现线程?

继承Thread:

可以直接调用Thread中的方法

实现Runnable接口:

实现Runnable接口,将实现类作为参数传递给Thread对象

实现Callable接口:

实现Callabale接口,创建FutureTask对象,将Callable作为参数传递给FutureTask对象,再将FutureTask对象传递给Thread类

4.用Runnable还是Thread?

Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继承其他类,当然是调用Runnable接口好了。

Thread:实际中用的相对较少,扩展性太差

Runnable,Callable:

扩展性比较强,优先使用Runnable接口,需要执行完有返回值可以选择Callable接口

5.Thread 类中的start() 和 run() 方法有什么区别?

start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。

当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

6.Java中Runnable和Callable有什么不同?

Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。

7.Java内存模型是什么?

Java内存模型规定和指引Java程序在不同的内存架构、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。这个关系定义了一些规则让程序员在并发编程时思路更清晰。比如,先行发生关系确保了:

  • 线程内的代码能够按先后顺序执行,这被称为程序次序规则。

  • 对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。

  • 前一个对volatile的写操作在后一个volatile的读操作之前,也叫volatile变量规则。

  • 一个线程内的任何操作必需在这个线程的start()调用之后,也叫作线程启动规则。

  • 一个线程的所有操作都会在线程终止之前,线程终止规则。

  • 一个对象的终结操作必需在这个对象构造完成之后,也叫对象终结规则。

  • 可传递性

8.Java中的volatile 变量是什么?

volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生,就是上一题的volatile变量规则。

9.什么是线程安全?Vector是一个线程安全类吗?

多个线程可能会同时运行同一段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它相似的ArrayList不是线程安全的。

10.Java中如何停止一个线程?

当run() 或者 call() 方法执行完的时候线程会自动结束,如果要手动结束一个线程,你可以用volatile 布尔变量或设置某个变量达到一定值的时候,来退出run()方法的循环或者是取消任务来中断线程。

11.Java中notify 和 notifyAll有什么区别?

notify()方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地。

而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行

12. 什么是线程池? 为什么要使用它?

创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)

13.如何写代码来解决生产者消费者问题?

在现实中你解决的许多线程问题都属于生产者消费者模型,就是一个线程生产任务供其它线程进行消费,你必须知道怎么进行线程间通信来解决这个问题。比较低级的办法是用wait和notify来解决这个问题,比较赞的办法是用Semaphore 或者 BlockingQueue来实现生产者消费者模型

14.Java多线程中的死锁

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务,死锁的发生必须满足以下四个条件:

  • 互斥条件:一个资源每次只能被一个进程使用。

  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  • 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。

15.Java中synchronized 和 ReentrantLock 有什么不同?

这两种方式最大区别就是对于Synchronized来说,它是java语言的关键字,是原生语法层面的互斥,需要jvm实现。而ReentrantLock它是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成。

16.详谈Synchronized

当Synchronized关键字修饰一个方法的时候,该方法叫做同步方法:java中的每个对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法的时候,表示将对象上锁,此时其它任何线程都无法再去访问synchronized方法了,直到之前的那个线程执行方法完毕后(或者是抛出了异常),那么将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法。

注意1:

如果一个对象有多个synchronized方法,某一个时刻某个线程已经进入到了某个synchronized方法,那么在该方法没有执行完毕前,其它线程是无法访问该对象的任何synchronzed方法的。

注意2:

如果某个Synchronized方法是static的,那么当线程访问该方法时,它锁的并不是Synchronized方法所在的对象,而是Synchronized方法所在的对象所对象的Class对象,因为java中无论一个类有多少个对象,这些对象会对应唯一一个class对象,因此当线程分别访问同一个类的两个对象的两个static Synchronized方法的时候,他们执行的顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行。

17.在Java中Lock接口与synchronized块的区别是什么?

.用法不一样。synchronized既可以加在方法上,也可以加载特定的代码块上,括号中表示需要锁的对象。而Lock需要显示地指定起始位置和终止位置。synchronzied是托管给jvm执行的,Lock锁定是通过代码实现的。

2.在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

3.锁的机制不一样。synchronized获得锁和释放的方式都是在块结构中,而且是自动释放锁。而Lock则需要开发人员手动去释放,并且必须在finally块中释放,否则会引起死锁问题的发生。

4.Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

5.synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁

18.synchronized 的原理是什么?有什么不足?

synchronized是 Java 内置的关键字,它提供了一种独占的加锁方式。

synchronized的获取和释放锁由JVM实现,用户不需要显示的释放锁,非常方便。

然而,synchronized 也有一定的局限性。

当线程尝试获取锁的时候,如果获取不到锁会一直阻塞。

如果获取锁的线程进入休眠或者阻塞,除非当前线程异常,否则其他线程尝试获取锁必须一直等待。

19.关于成员变量和局部变量

如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作的时候,他们对该成员变量是彼此影响的,也就是说一个线程对成员变量的改变会影响到另外一个线程;如果一个变量是局部变量,那么每个线程都会有一个该局部变量的拷贝,一个线程对该局部变量的改变不会影响到其它的线程。

20. 如果你提交任务时,线程池队列已满。会时发会生什么?

如果一个任务不能被调度执行那么ThreadPoolExecutor’s submit()方法将会抛出一个RejectedExecutionException异常。

21.volatile关键字的作用是?

保证变量的可见性。

在java内存结构中,每个线程都是有自己独立的内存空间(此处指的线程栈)。当需要对一个共享变量操作时,线程会将这个数据从主存空间复制到自己的独立空间内进行操作,然后在某个时刻将修改后的值刷新到主存空间。这个中间时间就会发生许多奇奇怪怪的线程安全问题了,volatile就出来了,它保证读取数据时只从主存空间读取,修改数据直接修改到主存空间中去,这样就保证了这个变量对多个操作线程的可见性了。换句话说,被volatile修饰的变量,能保证该变量的 单次读或者单次写 操作是原子的。

但是线程安全是两方面需要的 原子性(指的是多条操作)和可见性。volatile只能保证可见性,synchronized是两个均保证的。

volatile轻量级,只能修饰变量;synchronized重量级,还可修饰方法。

volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞。

22.守护线程和非守护线程有什么区别?

程序运行完毕,JVM 会等待非守护线程完成后关闭,但是 JVM 不会等待守护线程

23.线程的生命周期?

线程的生命周期包含5个阶段,包括:新建、就绪、运行、阻塞、销毁。

  • 新建:就是刚使用new方法,new出来的线程;

  • 就绪:就是调用的线程的start()方法后,这时候线程处于等待CPU分配资源阶段,谁先抢的CPU资源,谁开始执行;

  • 运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能;

  • 阻塞:在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如sleep()、wait()之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法,它们要再次等待CPU分配资源进入运行状态;

  • 销毁:如果线程正常执行完毕后或线程被提前强制性的终止或出现异常导致结束,那么线程就要被销毁,释放资源;

24.wait和sleep,notify()锁方面区别?

wait:让线程等待,同时立即释放锁

sleep():让线程休眠,但是不会释放锁

notify()或notifyAll(): 唤醒等待的线程,但是不会立即释放锁

25.什么情况下会出现线程安全问题?

多线程环境

有共享数据

有对共享数据的操作

26.Java中规定了线程有哪几种状态?

新建、就绪、阻塞、等待、计时等待、死亡

反射

1.Java反射机制的作用?

1)在运行时判断任意一个对象所属的类。

2)在运行时判断任意一个类所具有的成员变量和方法。

3)在运行时任意调用一个对象的方法

4)在运行时构造任意一个类的对象

2.什么是反射机制?

简单说,反射机制值得是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

3.哪里用到反射机制?

Spring 框架的 IoC 基于反射创建对象和设置依赖属性。

Spring MVC 的请求调用对应方法,也是通过反射。

JDBC 的 Class#forName(String className) 方法,也是使用反射。

4.反射机制的优缺点?

静态编译:在编译时确定类型,绑定对象,即通过

动态编译:运行时确定类型,绑定对象。动态编译最大限度的发挥了java的灵活性,体现了多态的应用,有利于降低类之间的耦合性。

一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中

它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编

译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如

这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能

的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功

能。

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它

满足我们的要求。这类操作总是慢于只直接执行相同的操作

5.反射中,Class.forName 和 ClassLoader 区别

java中class.forName()和classLoader都可用来对类进行加载。

class.forName()前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。

而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,077
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,552
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,400
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,176
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,812
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,894