Java基础高级面试题整理总结 下

简介: 55、throw与throws的区别throw:在方法里面抛出异常,只能明确的抛出一个异常对象名,由方法体内的语句处理异常。throws:在方法外面抛出异常,声明一个方法可能抛出的异常(允许无病呻吟),可以是多个,后面异常范围要比前面大,由该方法的调用者来处理异常

55、throw与throws的区别


throw:在方法里面抛出异常,只能明确的抛出一个异常对象名,由方法体内的语句处理异常。


throws:在方法外面抛出异常,声明一个方法可能抛出的异常(允许无病呻吟),可以是多个,后面异常范围要比前面大,由该方法的调用者来处理异常


56、运行时异常与受检异常有何异同


运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见错误,只要程序设计的没有问题就不会发生。


受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发


Java编译器要求方法必须声明抛出可能发生的受检异常,但是运行时异常不要求


57、列出一些你常见的运行时异常


ArithmeticException 算术异常


NullPointerException 空指针异常


ClassCastException 类转换异常


IndexOutOFBoundsException 下标越界异常


SecurityException 安全异常


IllegalArgumentException 非法参数异常


58、阐述fianl、finally、finalize的区别


final:如果一个类被声明为final,则这个类不能被继承;将变量声明为final,在声明时必须赋初始值,且在以后的引用中不可修改;将方法声明为final,则不能被重写


finally:通常放在try。。。catch。。的后面,为确保一段代码不管发生什么异常都要被执行,通常放一些释放外部资源的代码


finalize:object类中定义的方法,这个方法是在由垃圾收集器在销毁对象时调用的,通过重写finalize方法可以整理系统资源或者执行其他清理工作


59、类ExampleA继承Exception,类ExampleB继承ExampleA


有如下代码片断:


try {
    throw new ExampleB("b")
} catch(ExampleA e){
    System.out.println("ExampleA");
} catch(Exception e){
    System.out.println("Exception");
}


请问执行此段代码的输出是什么?


答:输出:ExampleA。




60、说出下面代码的运行结果。(此题的出处是《Java编程思想》一书)


class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
class Human {
    public static void main(String[] args) 
        throws Exception {
        try {
            try {
                throw new Sneeze();
            } 
            catch ( Annoyance a ) {
                System.out.println("Caught Annoyance");
                throw a;
            }
        } 
        catch ( Sneeze s ) {
            System.out.println("Caught Sneeze");
            return ;
        }
        finally {
            System.out.println("Hello World!");
        }
    }
}

答: Caught Annoyance


Caught Sneeze


Hello World!




61、List、Set、Map是否继承自Collection接口


List、Set是,Map不是。Map是键值对映射容器,Set无序且唯一、List有序不唯一


62、Collection和Collections的区别


Collection是一个接口,他是Set、List等容器的父接口;


Collections是一个工具类,提供一系列的排序、线程安全化等静态方法来辅助容器操作


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


List:以特定索引来存取元素,可以有重复元素


Set:不能存放重复元素


Map:保存键值对映射,映射关系可以是一对一或多对一。


64、阐述ArrayList、Vector、LinkedList的存储性能和特性


ArrayList:底层物理存储为线性的,线程不安全,查询效率高,删除、添加等操作效率低


Vector:底层物理存储为线性的,线程安全的,数据安全,效率比较低


LinkedList:底层物理存储为链表的,查询效率低,删除、添加等操作效率高


65、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?


TreeMap:要求存放的键值对映射的键必须实现Comparable接口,从而根据键值对进行排序


TreeSet:要求存放对象所属的类必须实现Comparable接口,当插入元素时会调用CompareTo()方法比较元素的大小


Collections:工具类的sort方法有两种重载形式


第一种:要求容器内存放的元素可比较,实现Compatator接口以实现元素的比较


第二种:不强制要求要求传入的元素可比较,但要传入第二个参数,即Comparator接口的子类型


66、Thread类的sleep()方法和Object类的wait()方法都可以让线程暂停执行,他们有什么区别?


sleep()方法:调用此方法会让当前线程进入阻塞状态,对象的锁依然保持,休眠时间到会自动进入就绪状态


wait()方法:调用此方法会让当前线程进入对象的等待池,放弃对象的锁,只有调用notify()方法才能唤醒等待池中的线程进入等锁池(如果线程重写获得对象的锁就可以进入就绪状态)


67、进程和线程的区别:


进程:是CPU调度和分派一个独立单位,执行时有独立的内存单元


线程:是进程的一个实体,是CPU调度和分派的基本单位,执行时可以共享内存


需要强调的是,不是线程越多,程序的性能越好


68、线程的sleep()方法和yield()方法有什么区别?


1)sleep方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程运行机会;yield方法只会给相同优先级或更高优先级线程运行机会


2)sleep方法执行完后进入阻塞状态;yield方法执行完后进入就绪状态


3)sleep方法声明抛出InterruptedException,yield方法没有声明任何异常


4)sleep方法比yield方法具有更好的可移植性


69、当一个线程进入一个对象的synchronized方法A后,其他线程是否可以进入此对象的synchronized方法B?


不能,其他线程只能访问该对象的非同步方法,因为synchronized修饰符要求执行方法时要获得对象的锁,如果一个线程已经进入A方法,说明对象的锁已经被取走,那么试图进入B方法的其他线程就只能在等锁池中等待对象的锁


70、请说出与线程同步已经线程调度相关的方法


1)wait():使一个线程处于阻塞(等待)状态,并且释放所持有的对象的锁


2)sleep():使当前线程进入阻塞状态,对象的锁依然保持,调用此方法需处理InterruptedException


3)notify():唤醒一个处于等待状态的线程,由JVM确定唤醒哪个线程,与优先级无关


4)notityAll():唤醒所有处于等待状态的线程,唤醒后不是所有线程都会进入就绪状态,只有获得锁的线程才会


71、编写多线程程序有几种实现方式?


Java5以前:继承Thread类、实现Runnable接口


两种方式都要通过重写run()方法,推荐使用后者,因为Java是单继承多实现,一个类如果继承了Thread就无法继承其他类了,所以使用Runnable接口更为灵活


Java5以后:增加实现Callable接口方法


72、synchronized关键字的用法


synchronized关键字可以将对象或者方法标记为同步


对象:synchronized(对象){。。。}:可以对本类对象(this)和其他类对象(new)加锁,无法得知哪些方法是被synchronize保护的


方法:synchronized void 方法名(参数){。。。}:只能对本类对象加锁,整个方法的所有语句加锁,可以显示得知方向是被synchronize保护的


73、同步和异步有什么异同


同步:发送一个请求,需要等待返回,然后才能发送下一个要求。举例:银行的转账系统、数据库的保存操作


异步:发送一个请求,不需要等待返回,就可以发送下一个请求。举例:大多数项目优先使用异步交互


74、启动一个线程是调用run()还是start()方法


调用start()方法,这意味着线程可以由JVM调度并执行,并不意味着线程会立即运行。run()方法是线程启动后要进行回调的方法。


75、什么是线程池


线程池就是事先创建若干个可执行的线程放入一个池中,需要的时候从池中获取线程不用自行创建,使用完毕后放回池中不需要销毁线程,从而减少创建和销毁线程对象的开销


76、线程生命周期


注:阻塞状态有多种情况:a.调用wait()方法进入等待池、b.执行同步synchronize方法进入等锁池、c.调用sleep或者join方法等待休眠或者其他其他线程结束、d.发生了I/O中断


77、简述synchronized和java.util.concurrent.locks.Lock的异同


相同点:Lock的Java5以后引入的新的API,能完成synchronized所实现的所有功能


不同点:Lock比synchronized性能更好,不强制要求一定要获得锁;Lock要求程序员手工释放锁,synchronized会自动释放锁


78、Java中如何实现序列化,有什么意义?


实现序列化需要让一个类实现Serializable接口(该接口可以标注该类对象是可被序列化的),然后用一个输出流建立对象输出流并通过writeObject方法就可以写出对象;反序列化可以用一个输入流建立对象输入流,并通过readObject方法从流中读取对象。


意义:序列化为了解决对象流读写操作时可能引发的数据乱序的问题,能够实现对象的持久化,还能够用于对象的深度克隆


79、Java中有几种类型的流?


字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。


80、写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数


public final class MyUtils{
private MyUtils(){
throw new AssertionError();
}
public static int countWordInFile(String filename,String word){
BufferReader br = new BufferReader(new FileReader(filename));
int count = 0;
String line = null;
while((line = br.readLine()) != null){
int index = -1;
while(line.length() >= word.length() && (index = line.indexOf(word)) >= 0){
count++;
line = line.substring(index + word.length());
}
}
br.close();
return count;
}
}

81、如何用一个Java代码列出当前文件下的文件


public static void main(String[] args){
File f = new File(“/Users/FileDemo”);
for(File temp : f.listFiles()){
if(temp.isFile()){
System.out.println(“文件:”+ temp.getAbsolutePath());
}
}
}

82、如何用一个Java代码列出一个目录下的所有文件(需要对文件夹继续展开)


public void ListFile1(String path){
File f = new File(path);
for(File temp : f.listFiles()){
if(temp.isDirectory){
System.out.println(“文件夹:”+ temp.getAbsolutePath());
ListFile1(temp.getAbsolutePath());//递归调用
}else{
System.out.println(“文件:”+ temp.getAbsolutePath());
}
}
}


83、用Java套接字编程实现一个多线程的回显(echo)服务器(不会)


public class EchoServer{
private static final int ECHO_PORT = 6789;
public static void main(String[] args){
}
}


84、XML文档定义有几种形式?它们之间有什么本质的区别?解析XML文档有哪几种方式?


XML是可扩展的标记语言(Extensible Markup Language)


定义文档:DTD和Scheme两种形式


本质区别:Schema本身也是一个XML文件,可以被XML解析器解析,而且可以为XML承载的数据定义类型,约束能力较之DTD更强大。


XML文档解析方式:


DOM(文档对象模型,Document Object Model):不适合处理大型文件

SAX(Simple API for XML):顺序读取XML文件,不需要一次全部装载整个文件

StAX(Streaming API for XML):把XML文件当成一个事件流来处理



85、你在项目中哪些地方用到了XML?


XML的主要作用有两个方面:数据交换和信息配置。


数据交换:此项功能几乎已经被JSON(JavaScript Object Notation)取代


信息配置:在项目中,将作为配置信息的硬代码写在xml文件中,Java中的很多框架都是这样做的


86、阐述JDBC操作数据库的步骤


1)导入驱动jar包


2)创建驱动类对象


3)连接数据库


4)操作数据库


5)关闭数据库


87、Statement和PreparedStatement有什么区别?哪个性能更好?


1)Statement会引起注入,PreparedStatement防止注入,增强SQL的安全性


2)PreparedStatement中的SQL语句是可以带参数的


3)PreparedStatement是预编译语句,批量处理SQL语句时有明显性能上的优势


88、在进行数据库编程时,连接池有什么用?


为了提升系统访问数据库的性能,可以事先创建若干连接到连接池中,需要时直接从连接池中获取,使用结束时归还连接池而不必关闭连接。避免了频繁创建和是否连接所造成的开销


89、使用JDBC操作数据库,如何提升读取数据的性能?如何提升更新数据库的性能?


1)通过指定结果集(ResultSet)对象的setFetchSize()方法指定每次抓取的记录数


2)可以使用PreparedStatement语句构建批处理,将若干SQL语句置于一个批处理中执行


90、什么是DAO模式


DAO(Data Access Object)是一个为访问数据库提供抽象接口的对象,接口中定义了和数据库交互的所有事务方法。当应用程序需要数据库数据时,则创建一个单独的类实现这个接口,在不暴露实现细节的前提下进行数据访问操作


91、事务的特性(ACID)是指什么?


1)原子性(Atomic):事务中的各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败


2)一致性(Consistent):事务结束后系统状态是一样的


3)隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态


4)持久性(Durable):事务完成后,即使发生灾难性的故障,通过日志和同步备份可以在故障发生后重建数据


92、JDBC中如何进行事务的处理


JDBC中,Connection提供的事务处理的方法:


commit():通过调用setAutoCommit(false)设置手动提交事务,当事务完成后用commit()显示提交事务


rollback():在事务发生异常时用rollback()进行事务回滚


Savepoint:设置保存点让事务回滚到指定位置


93、JDBC能否处理Blob和Clob?


能处理。


Blob(Binary Large Object)大二进制对象,是为存储大的二进制数据而设计的、Clob(Character Large Object)大字符对象,是为了存储大的文本数据而设计的。JDBC中的PreparedStatement和ResultSet都提供了方法来支持Blob和Clob操作


94、简述正则表达式及其用途


简述:正则表达式就是记录文本规则的代码。


用途:用来查找某些符合复杂规则的字符串


95、Java中是如何支持正则表达式操作的?


1)Java中可以用Pattern类表示正则表达式对象,一般代码如下


Pattern p = Pattern.compile("a*b");


Matcher m = p.matcher("aaaaab");


2)Java中的String类也提供了支持正则表达式操作的方法,包括matches()、replaceAll()等


96、如果要从字符串中截取第一个英文左括号之前的字符串,例如:北京市(朝阳区)(西城区)(海淀区),截取结果为:北京市,那么正则表达式怎么写?


public static void main(String[] args){
String str = "北京市(朝阳区)(西城区)(海淀区)";
Pattern p = Pattern.compile(“.*?(?=\\()”);
Matcher m = p.matcher(str);
if(m.find()){                      //查找与该模式匹配的下一个子序列
System.out.println(m.group());   //返回匹配的子序列
}
}


97、获得一个类的类对象有哪些方式


1)类型.class 如:String.class


2)对象.getClass() 如:student.getClass()


3)class.forName() 如:Class.forName(“java.lang.String”)


98、如何通过反射创建对象


1)通过类对象调用newInstance()方法,例如:String.class.newInstance()


2)通过类对象调用getConstructor()方法获得构造器对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance(“Hello”);


99、如何通过反射获取和设置对象私有字段的值


可以通过类对象调用getDeclaredField()方法,再通过setAccessible(true)将其设置成可访问的,接下来可以通过get/set方法来获取/设置字段的值了(字段可以是基本类型、对象类型)


Field f = clazz.getDeclaredField(fs[i]);


f.setAccessible(true);


Object target = f.get(target);


100、如何通过反射调用对象方法


public static void main(String[] args) throws Exception{


String str = “hello”;


Method  m = str.getClass().getMethod(“toUpperCase”);


System.out.println(m.invoke(str));     //HELLO


}


101、简述一下面向对象的“六原则一法则”


1)单一职责原则:一个类只有单一职责,就是高内聚


2)开闭原则:软件实体应该对扩展开放,对修改关闭


3)依赖倒转原则:面向接口编程,声明方法和变量尽量使用抽象类型,因为抽象类型可以被他的任何一个子类型替代


4)里氏替换原则:任何时候都可以用子类型替换掉父类型


5)接口隔离原则:一个接口只应该描述一种能力,接口也是高度内聚的


6)合成聚合复用原则:优先使用聚合或合成关系复用代码,优先采用Has-A(关联)关系而不是Is-A(继承)关系复用代码


7)迪米特法则:又叫最小知识法则,一个对象应该对其他对象尽可能少的了解,就是低耦合


102、为什么要优先使用组合而不是继承


继承破坏封装性,父类有很多细节都是对子类可见的,如果父类的实现发生改变,那么子类的实现也将发生改变,导致了子类行为的不可预知性,并且从父类继承来的实现是无法在运行期动态改变的,降低了应用的灵活性。组合将已有的对象组合到新对象中,因此新对象可以调用已有对象的功能,组合关系中各个对象的内部实现是隐藏的,我们只能通过接口调用,因此我们完全可以在运行期间实现同样接口的另外一个对象来替代原对象,从而灵活实现运行期间的行为控制


103、简述一下你了解的设计模式


使用设计模式是为了可重用代码、保证代码的可靠性、让代码更容易被他人理解。常用设计模式如下:


工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态),当得到子类的实例后,开发人员可以调用父类中的方法,而不必考虑到底返回哪一个子类实例

代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用

适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起使用的类能够一起工作

模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器形式出现,然后声明一些抽象方法来迫使子类实现剩余的逻辑


104、用Java写一个单例类


两个条件:构造器私有、公开的静态方法向外界返回唯一实例


1)饿汉式模式


public class A{
private A(){}                    //将构造器自由化,只能被本类实例化
private static A  instance = new A();//实例化对象
public static A  getInstance(){
return instance;              //此类对象只能通过此方法获取返回值
}
}

2)懒汉式模式


public class A{
private A(){}
private static A  instance = null;
public static A  getInstance(){
if(instance == null){
instance = new A();
return instance;
}
}
}



105、用Java写一个冒泡排序

public static void main(String[] args){
int[] arr = {1,2,3,4,8,5,6,1,2};
for(int i=0;i<arr.length;i++){
for(int j=i+1;j<arr.length;j++){
if(arr[i]>arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
System.out.print(arr[i]);
}
}


106、用Java写一个折半查找


public static int harfSearch(int[] srcArray,int des){
int low = 0;
int high = srcArray.length-1;
while(low<=high){
int middle = (low+high)/2;
if(des == srcArray[middle]){
return middle;
}else if(des<srcArray[middle]){
high = middle-1;
}else {
low = middle+1;
}
}
return -1;
}
public static void main(String[] args) {
int[] src = new int[] {1, 3, 5, 7, 8, 9}; 
System.out.println(harfSearch(src, 3));
}



107、Java有几种设计模式


1)单例设计模式:让类的构造方法私有化,同时提供一个静态方法去实例化这个类


2)单工厂设计模式:写一个类,让他制造出我们想要的所有对象


3)适配器设计模式:通过写一个适配器类,里面写了所有的抽象方法,但是这些方法是空的


4)模板设计模式:在类中定义一个抽象方法,由子类去实现


目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
26天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
66 14
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
1月前
|
存储 缓存 Oracle
Java I/O流面试之道
NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
Java I/O流面试之道
|
1月前
|
Java 编译器 程序员
Java面试高频题:用最优解法算出2乘以8!
本文探讨了面试中一个看似简单的数学问题——如何高效计算2×8。从直接使用乘法、位运算优化、编译器优化、加法实现到大整数场景下的处理,全面解析了不同方法的原理和适用场景,帮助读者深入理解计算效率优化的重要性。
35 6
|
1月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
62 4
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
133 4
|
2月前
|
存储 安全 算法
Java面试题之Java集合面试题 50道(带答案)
这篇文章提供了50道Java集合框架的面试题及其答案,涵盖了集合的基础知识、底层数据结构、不同集合类的特点和用法,以及一些高级主题如并发集合的使用。
124 1
Java面试题之Java集合面试题 50道(带答案)
|
2月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
91 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)