13道面试题

1、常用的集合类有哪些?比如List如何排序?

image.png
最常用的集合类是 List 、set和 Map。

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

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

Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。

2Object类中,有哪些方法?列举三个以上。

构造方法,toString(),equals,hashCode,getClass,finalize,clone,三个wait(),notify,notifyAll.

A:void finalize()

当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

B:Class getClass()

获取对象的字节码文件的描述类,后面再讲反射的时候还会在说这个类。String name = s.getClass().getName();

C:int hashCode()

获取对象的哈希值。其实就是对象的内存地址值十进制表示

D:String toString()

返回对象的字符串表示。表示格式:

getClass().getName()+"@"+Integer.toHexString(hashCode());

一般我们输出对象名的时候,其实底层调用的就是该对象的 toString()方法。这种返回没有意义,所以,我们会重写这个方法,显示类的成员变量信息。

E:boolean equals(Object obj)

用于比较两个对象的地址值是否相同。

我们获取对象后,比较它的地址值意义不大。所以也会对这个方法进行重写。重写要完成什么功能,是根据需求定的。

3Java中的异常有哪几类?分别怎么使用?

  1. Error:系统级的错误,eg:内存溢出 -- OutOfMemoryError
  2. Exception:程序级的错误 -- 通常是由于程序员逻辑不当引起的,可以修改代码来解决的。

编译时异常;运行时异常;自定义异常。

  1. 检出异常,非检出异常。检出异常需要try...catch才能编译通过。非检出异常不用try...catch也能编译通过。

RuntimeException是非检出异常,不需要try...catch也能编译通过。

IoException,SQLException等等其他所有异常都是检出异常,必须要try...catach才能编译通过。

4、如何用Java分配一段连续的1G的内存空间?需要注意些什么?

ByteBuffer.allocateDirect(102410241024) 注意内存溢出

5、如何格式化日期?

使用 SimpleDateFormat 类或者 joda-time 库来格式日期。

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

使用new关键字

} → 调用了构造函数

使用Class类的newInstance方法

} → 调用了构造函数

使用Constructor类的newInstance方法

} → 调用了构造函数

使用clone方法

} → 没有调用构造函数

使用反序列化

} → 没有调用构造函数

7final有哪些用法?

final的用法:修饰类;修饰方法;修饰成员变量;修饰局部变量。

1.被final修饰的类不可以被继承 2.被final修饰的方法不可以被重写 3.被final修饰的变量不可以被改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。 4.被final修饰的方法,JVM会尝试将其内联,以提高运行效率 5.被final修饰的常量,在编译阶段会存入常量池中。

8、如何实现集合排序?

第一种称为自然排序,参与排序的对象需实现comparable接口,重写其compareTo()方法,方法体中实现对象的比较大小规则。

第二种叫定制排序,或自定义排序,需编写匿名内部类,先new一个Comparator接口的比较器对象,同时实现compare()其方法; 然后将比较器对象传给Collections.sort()方法的参数列表中,实现排序功能;

重点掌握

Collections.sort(list,new Comparator(){ 
    public int compare(String o1, String o2) { 
    return o1.length()-o2.length();
    }  
}); 
System.out.println(list);    

自定义排序

Collections.sort(list,new Comparator(){ 
    public int compare(Point2 o1, Point2 o2) { 
        int len1 =o1.getX()*o1.getX()+o1.getY()*o1.getY(); 
        int len2 =o2.getX()*o2.getX()+o2.getY()*o2.getY();
        return len1-len2;
      }
}); 
System.out.println(list);

Random random = new Random(); 
for(int i=0;i<10;i++){
    list.add(random.nextInt(100));
} 
System.out.println(list); 
Collections.sort(list); 
System.out.println(list);

9、如何打印数组信息?

使用 for 或(fore)循环

for(int i=0;i


使用 Arrays.toString() 打印。

public class Demo { public static void main(String[] args) {
    String[] infos = new String[] {"Java", "Android", "C/C++", "Kotlin"};
    System.out.println(Arrays.toString(infos));
  }
}
​

使用 Arrays.deepToString() 方法打印。如果数组中有其它数组,即多维数组,也会用同样的方法深度显示。

public class Demo { public static void main(String[] args) {
    String[] infos = new String[] {"Java", "Android", "C/C++", "Kotlin"};
​    System.out.println(Arrays.deepToString(infos));
  }
}

数组如何扩容?

10、遍历ArrayList时,如何正确移除一个元素?

方法一、for循环遍历public class Test1{

public static void main(String args[]) {
    List aList = new ArrayList();
    aList.add("a");
    aList.add("ab");
    aList.add("abc");
    aList.add("abc");
    aList.add("abcr");
    aList.add("abc");
    aList.add("abcf");
    aList.add("abc");
    aList.add("abdc");
    for(int i=0;i

方法二、迭代遍历

public static void main(String args[]) {
    List aList = new ArrayList();
    aList.add("a");
    aList.add("ab");
    aList.add("abc");
    aList.add("abc");
    aList.add("abcr");
    aList.add("abc");
    aList.add("abcf");
    aList.add("abc");
    aList.add("abdc");
    Iterator iter = aList.iterator();
    while(iter.hasNext()) {
        if(iter.next().equals("abc")) {
            iter.remove();
        }
    }
        System.out.println(aList);
}

11String类的常用方法都有哪些?

equals:字符串是否相同

length:字符串字符数

indexOf:目标字符或字符串在源字符串中位置下标

lastIndexOf:目标字符或字符串在源字符串中最后一次出现的位置下标

substring:截取字符串

charAt:获取指定下标位置的字符

startsWith:是否以目标字符串开头

endsWith:是否以目标字符串结束

valueOf:其他类型转字符串

toLowerCase:字符串转小写

toUpperCase:字符串转大写

trim:去字符串首尾空格

split:以某正则表达式分割字符串

replace:字符串替换

replaceAll:带正则字符串替换

replaceFirst:替换第一个出现的目标字符串

equalsIgnoreCase:忽略大小写后字符串是否相同

compareTo:根据字符串中每个字符的Unicode编码进行比较

compareToIgnoreCase:根据字符串中每个字符的Unicode编码进行忽略大小写比较

codePointAt:指定下标的字符的Unicode编码

concat:追加字符串到当前字符串

isEmpty:字符串长度是否为0

contains:是否包含目标字符串

format:格式化字符串

getBytes:获取字符串的字节数组

getChars:获取字符串的指定长度字符数组

toCharArray:获取字符串的字符数组

join:以某字符串,连接某字符串数组

matches:字符串是否匹配正则表达式

12JSP有哪些内置对象?作用分别是什么?

· request封装客户端的请求,其中包含来自 get 或 post 请求的参数;

· response:封装服务器对客户端的响应;

· pageContext:通过该对象可以获取其他对象;

· session:封装用户会话的对象;

· application:封装服务器运行环境的对象;

· out:输出服务器响应的输出流对象;

· config:Web 应用的配置对象;

· page:JSP 页面本身(相当于 Java 程序中的 this);

· exception:封装页面抛出异常的对象。

13JSP的四种作用域?

· page:代表与一个页面相关的对象和属性。

· request:代表与客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。

· session:代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。

· application:代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个Web 应用程序,包括多个页面、请求和会话的一个全局作用域。

14String/StringBuffer/StringBuilder的区别,扩展再问他们的实现?

String 值不可变 字符串常量 操作少量数据 StringBuffer 值可变是线程安全 字符串变量,适用于多线程操作大量数据 StringBuilder 值可变是线程不安全的 字符串变量,适用于单线程操作大量数据

15 Servlet的生命周期?

实例、初始化、服务处理(接收请求,处理请求,返回结果)、销毁。

16Session/Cookie的区别?

Cookie是采用客户端保持状态的方案,内容存放在客户的浏览器上,不安全,cookie,未设置过期时间一般保存在内存中,成为会话Cookie,一旦浏览器关闭,这个Cookie也就关闭;若设置了过期时间,则是保存在硬盘上,下次依然会有效 Session是采用服务器保持状态的方案,内容存放在服务器上,更为安全,当有一个客户端要与服务器建立连接时,服务器会检索请求是否包含一个session标识,若包含,则将这个session检索出来。

17、触发器的作用是什么?

触发器是一种用来保障参照完整性的特殊的存储过程,它维护不同表中数据间关系的有关规则。当对指定的表进行某种特定操作(如:Insert,Delete或Update)时,触发器产生作用。触发器可以调用存储过程。

18、索引的两种类型?

索引分单列索引和组合索引。 单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。 组合索引,即一个索引包含多个列

19、简述Spring中常用注解?

  1. @Component :标准一个普通的spring Bean类。
  2. @Repository:标注一个DAO组件类。
  3. @Service:标注一个业务逻辑组件类。
  4. @Controller:标注一个控制器组件类。
  5. @Resource:注入组件

20、过滤器和拦截器

过滤器和拦截器触发时机不一样:过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

21、、什么是跨域?
浏览器解析Ajax时,发起url请求违反了同源策略时,称之为跨域.(三要素)
什么时候用跨域?
一般A服务器需要从B服务器中获取数据是,可以采用跨域.
什么是JSONP?
JSONP是JSON的一种使用模式 利用JavaScript中的src属性进行跨域请求(自定义回调函数 将返回值进行特殊格式封装)
什么是CORS
CORS是当前实现跨域的主流方式,现在所有的主流浏览器都支持,需要在服务器端配置是否允许跨域的配置,只要配置了(在响应头中添加允许跨域的标识),则同源策略不生效,则可以实现跨域.

22、、创建线程池有哪几种方式?简述特点、

· extends Thread -- 重写run方法(定义执行的任务)

· implements Runnable接口 -- 重写run方法(执行的任务)

  1. newSingleThreadExecutor():它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目;
  2. newCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列;
  3. newFixedThreadPool(int nThreads):重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。这意味着,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现;如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目 nThreads;
  4. newSingleThreadScheduledExecutor():创建单线程池,返回 ScheduledExecutorService,可以进行定时或周期性的工作调度;
  5. newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()类似,创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程;
  6. newWorkStealingPool(int parallelism):这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序;
  7. ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是ThreadPoolExecutor的封装。

16、什么是乐观锁和悲观锁?

观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。

悲观锁

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资 源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁 等,读锁,写锁等,都是在做操作之前先上锁。Java 中 synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现。

乐观锁

总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以 使用版本号机制和

CAS 算法实现。乐观锁适用于多读的应用类型,这样可以提 高吞吐量,像数据库提供的类似于 write_condition 机制,其实都是提供的乐 观锁。在 Java 中

java.util.concurrent.atomic 包下面的原子变量类就是使用了 乐观锁的一种实现方式 CAS 实现的。

两种锁的使用场景

从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一 种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的 时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的 情况,一般会经常产生冲突乐。

23、hibernatemybatis/ibatis的区别?

相同点:屏蔽jdbc api的底层访问细节,使用我们不用与jdbc api打交道,就可以访问数据。

jdbc api编程流程固定,还将sql语句与java代码混杂在了一起,经常需要拼凑sql语句,细节很繁琐。

ibatis的好处:屏蔽jdbc api的底层访问细节;将sql语句与java代码进行分离;提供了将结果集自动封装称为实体对象和对象的集合的功能,queryForList返回对象集合,用queryForObject返回单个对象;提供了自动将实体对象的属性传递给sql语句的参数。

Hibernate是一个全自动的orm映射工具,它可以自动生成sql语句,ibatis需要我们自己在xml配置文件中写sql语句,hibernate要比ibatis功能负责和强大很多。因为hibernate自动生成sql语句,我们无法控制该语句,我们就无法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate可以很好帮我们完成,但是,对于特别复杂的查询,hibernate就很难适应了,这时候用ibatis就是不错的选择,因为ibatis还是由我们自己写sql语句。

springmvc的启动流程
Ajax
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。