1、常用的集合类有哪些?比如List如何排序?
最常用的集合类是 List 、set和 Map。
List特点:元素有放入顺序,元素可重复的。
Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉。
Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。
2、Object类中,有哪些方法?列举三个以上。
构造方法,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)
用于比较两个对象的地址值是否相同。
我们获取对象后,比较它的地址值意义不大。所以也会对这个方法进行重写。重写要完成什么功能,是根据需求定的。
3、Java中的异常有哪几类?分别怎么使用?
- Error:系统级的错误,eg:内存溢出 -- OutOfMemoryError
- Exception:程序级的错误 -- 通常是由于程序员逻辑不当引起的,可以修改代码来解决的。
编译时异常;运行时异常;自定义异常。
- 检出异常,非检出异常。检出异常需要try...catch才能编译通过。非检出异常不用try...catch也能编译通过。
RuntimeException是非检出异常,不需要try...catch也能编译通过。
IoException,SQLException等等其他所有异常都是检出异常,必须要try...catach才能编译通过。
4、如何用Java分配一段连续的1G的内存空间?需要注意些什么?
ByteBuffer.allocateDirect(102410241024) 注意内存溢出
5、如何格式化日期?
使用 SimpleDateFormat 类或者 joda-time 库来格式日期。
6、java创建对象的几种方式?
使用new关键字
→ 调用了构造函数
使用Class类的newInstance方法
→ 调用了构造函数
使用Constructor类的newInstance方法
→ 调用了构造函数
使用clone方法
→ 没有调用构造函数
使用反序列化
→ 没有调用构造函数
7、final有哪些用法?
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<String>(){
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
System.out.println(list);
自定义排序
Collections.sort(list,new Comparator<Point2>(){
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<array.length;i++){
System.out.println(array[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<String> 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<aList.size();i++) {
if(aList.get(i).equals("abc")) {
System.out.println(i+":"+aList.get(i));
aList.remove(i); // 删除后 下标调整 导致漏删
}
}
System.out.println(aList);
}
方法二、迭代遍历
public static void main(String args[]) {
List<String> 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<String> iter = aList.iterator();
while(iter.hasNext()) {
if(iter.next().equals("abc")) {
iter.remove();
}
}
System.out.println(aList);
}
11、String类的常用方法都有哪些?
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:字符串是否匹配正则表达式
12、JSP有哪些内置对象?作用分别是什么?
· request:封装客户端的请求,其中包含来自 get 或 post 请求的参数;
· response:封装服务器对客户端的响应;
· pageContext:通过该对象可以获取其他对象;
· session:封装用户会话的对象;
· application:封装服务器运行环境的对象;
· out:输出服务器响应的输出流对象;
· config:Web 应用的配置对象;
· page:JSP 页面本身(相当于 Java 程序中的 this);
· exception:封装页面抛出异常的对象。
13、JSP的四种作用域?
· page:代表与一个页面相关的对象和属性。
· request:代表与客户端发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。
· session:代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。
· application:代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个Web 应用程序,包括多个页面、请求和会话的一个全局作用域。
14、String/StringBuffer/StringBuilder的区别,扩展再问他们的实现?
String 值不可变 字符串常量 操作少量数据 StringBuffer 值可变是线程安全 字符串变量,适用于多线程操作大量数据 StringBuilder 值可变是线程不安全的 字符串变量,适用于单线程操作大量数据
15、 Servlet的生命周期?
实例、初始化、服务处理(接收请求,处理请求,返回结果)、销毁。
16、Session/Cookie的区别?
Cookie是采用客户端保持状态的方案,内容存放在客户的浏览器上,不安全,cookie,未设置过期时间一般保存在内存中,成为会话Cookie,一旦浏览器关闭,这个Cookie也就关闭;若设置了过期时间,则是保存在硬盘上,下次依然会有效 Session是采用服务器保持状态的方案,内容存放在服务器上,更为安全,当有一个客户端要与服务器建立连接时,服务器会检索请求是否包含一个session标识,若包含,则将这个session检索出来。
触发器的作用是什么?
触发器是一种用来保障参照完整性的特殊的存储过程,它维护不同表中数据间关系的有关规则。当对指定的表进行某种特定操作(如:Insert,Delete或Update)时,触发器产生作用。触发器可以调用存储过程。
索引的两种类型?
索引分单列索引和组合索引。 单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。 组合索引,即一个索引包含多个列
hibernate和mybatis/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语句。
简述Spring中常用注解?
答案:
- @Component :标准一个普通的spring Bean类。
- @Repository:标注一个DAO组件类。
- @Service:标注一个业务逻辑组件类。
- @Controller:标注一个控制器组件类。
- @Resource:注入组件
过滤器和拦截器
过滤器和拦截器触发时机不一样:过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
springmvc的启动流程
Ajax
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。
什么是AOP?
在运行时,动态的将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。AOP即面向切面编程。使用切面编程,可以将一些系统性的代码提取出来,独立实现,与核心业务代码剥离,比如权限管理、事务管理、日志记录等等。AOP是spring提供的关键特性之一。
AOP分为静态AOP和动态AOP
14、如何实现跨域?
使用注解(@CrossOrigin)
15、创建线程池有哪几种方式?简述特点、
· extends Thread -- 重写run方法(定义执行的任务)
· implements Runnable接口 -- 重写run方法(执行的任务)
- newSingleThreadExecutor():它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目;
- newCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列;
- newFixedThreadPool(int nThreads):重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。这意味着,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现;如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目 nThreads;
- newSingleThreadScheduledExecutor():创建单线程池,返回 ScheduledExecutorService,可以进行定时或周期性的工作调度;
- newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()类似,创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程;
- newWorkStealingPool(int parallelism):这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序;
- ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是ThreadPoolExecutor的封装。
16、什么是乐观锁和悲观锁?
观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。
悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资 源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁 等,读锁,写锁等,都是在做操作之前先上锁。Java 中 synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现。
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以 使用版本号机制和
CAS 算法实现。乐观锁适用于多读的应用类型,这样可以提 高吞吐量,像数据库提供的类似于 write_condition 机制,其实都是提供的乐 观锁。在 Java 中
java.util.concurrent.atomic 包下面的原子变量类就是使用了 乐观锁的一种实现方式 CAS 实现的。
两种锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一 种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的 时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的 情况,一般会经常产生冲突乐
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。