- 什么是程序的copy
答: 想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克隆针对的是类的实例 - 浅拷贝和深海拷贝的区别是
答:浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝
深拷贝:两个对象都拥有各个独立的数据,不会相互影响。 - 拷贝的工具类中谁的效率最高 为什么
答: cgilb beanutils最高 Apache BeanUtils最差
因为apanche Beanutils为了追求完美 非常多的校验、兼容、日志打印等代码,过度的包装导致性能下降严重 - SimplateDateFormat方法中 y和Y的区别
答 因为不同的国家对新年第一天的定义不一样导致 Y y有区别 WEEK - 三目运算符中的对象和基本类型比较为什么会出现空指针
答::由于使用了三目运算符,并且第二、第三位操作数分别是基本
类型和对象。所以对对象进行拆箱操作,由于该对象为 null,所以在拆箱过程中调用到了null - hashMap 中采用的扩容机制的条件是什么
答:其实,HashMap 的扩容条件就是当 HashMap 中的元素个数(size)超过临界值(threshold)时就会自动扩容。 - hashMap为什么要指定大小
答:一个合理的初始化容量可以有效的提高性能 ,如果我们没有设置初始容量大小,
随着元素的不断增加,HashMap 会发生多次扩容,而 HashMap 中的扩 容机制决定了每次扩容都需要重建 hash 表,是非常影响性能的 - 扩容规则是什么
答: HashMap 会采用第一个大于该数值的 2 的幂作为初始化
容量(大约在hash存储3/4的情况下再次扩容) - 如果在知道hashMap内存的情况下怎么建表
答:Maps.newHashMapWithExpectedSize(数) - 为什么禁止使用 Executors 创建线程池?
- java开发手册中明确指明 创建线程的时候不要用Executors创建线程 池, 而是推荐使用ThreadpoolExecutors
- 允许请求长度为Integer_max_value可能会堆积大量的请求,导致内存溢出
- 允许请求创建线程为Integer_max_value可能会创建大量线程导致内存溢出
- 原因
- 导致 OOM 的其实是 LinkedBlockingQueue.offer 方法。
- Java 中 的 BlockingQueue 主 要 有 两 种 实 现, 分 别 是 ArrayBlockingQueue 和 LinkedBlockingQueue
- newFixedThreadPool 中创建 LinkedBlockingQueue 时,并未指定容
量。此时,LinkedBlockingQueue 就是一个无边界队列,对于一个无边界队列来说,是可以不断的向队列中加入任务的,这种情况下就有可能因为任务过多而导致内存溢出问题 - 解决办法在创建线程时使用
new ThreadPoolExecutor(指定,指定)
public class ExecutorsDemo {
private static ThreadFactory namedThreadFactory = new
ThreadFactoryBuilder()
.setNameFormat("demo-pool-%d").build();
private static ExecutorService pool = new ThreadPoolExecutor(5, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new
ThreadPoolExecutor.
AbortPolicy());
public static void main(String[] args) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
pool.execute(new SubThread());
}
}
}
- 为什么ArrayList中subList不能强行转化为ArrayList
- SubList 并没有重新创建一个 List,而是直接引用了原有的 List(返回了父类的视图),只是指定了一下他要使用的元素的范围而已(从fromIndex(包含),到 toIndex(不包含))。
- SubList 只是 ArrayList 的内部类,他们之间并没有集成关系,故无法直接进行强制类型转换。
- List 的 subList 方法并没有创建一个新的 List,而是使用了原 List 的视图,这个视图使用内部类 SubList 表示
- 如果需要对 subList 作出修改,又不想动原 list。那么可以创建 subList 的一个拷贝:
- String中拼接方式 以及为什么不能在for循环中+
- concat Stringbuffer中的append
- String在for中+ ==new StringBulider.append…toString
- StringBuffer 和 StringBuilder区别
- append 会直接拷贝字符到内部的字符数组中,如果字符数组长度不够会进行扩展
- StringBuffer 和 StringBuilder 类似,最大的区别就是 StringBuffer
是线程安全的 加入了 synchronized
- 为什么在foreach中禁止使用add/remave
- 在增强 for 循环中,集合遍历是通过 iterator
进行的,但是元素的 add/remove 却是直接使用的集合类自己的方法。这就导致iterator 在遍历的时候,会发现有一个元素在自己不知不觉的情况下就被删除 / 添加了,就会抛出一个异常 - fail-fast,即快速失败,它是 Java 集合的一种错误检测机制。当多个线程对集
合(非 fail-safe 的集合类)进行结构上的改变的操作时,有可能会产生 fail-fast 机制,
- 为什么不要使用日志的api
- 为了在应用中屏蔽掉底层日志框架的具体实现。这样的话,即使有一天要更换代码的日志框架,只需要修改 jar 包,最多再改改日志输出相关的配置文件就可以了。这就是解除了应用和日志框架之间的耦合。
- 最佳实践就是在应用中使用如 Log4j + SLF4J 这样的组合来进行日志输出
- 为什么禁止定义SimpleDateFormat 为static类型
- SimpleDateFormat是线程不安全的类 一般不要定义为static 如果非要定义要加上锁 或者使用DateUtils
- SimpleDateFormat 中的 format 方法在执行过程中,会使用一个成员变量calendar 来保存时间。这其实就是问题的关键
- 由于我们在声明 SimpleDateFormat 的时候,使用的是 static 定义的。那么这 个 SimpleDateFormat 就 是 一 个 共 享 变 量, 随 之SimpleDateFormat 中 的calendar 也就可以被多个线程访问到
- new Date()
new Date()获取的是计算机时间
打印美国时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
System.out.println(sdf.format(Calendar.getInstance().getTime()))
- 解决办法
- 使用局部变量
- 对于共享变量进行加锁
- 使用ThreadLocal保证每一个线程独一无二
- 使用DateTimeFormatter
String dateStr= "2016 年 10 月 25 日 ";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy 年 MM 月 dd 日 ");
LocalDate date= LocalDate.parse(dateStr, formatter);
// 日期转换为字符串
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy 年 MM 月 dd 日 hh:mm a");
String nowStr = now .format(format);
- 为什么禁止开发人员使用 isSuccess 作为变量名?
- pojo中不要再boolean中命名加上is,因为他的属性方法也是is开头,再序列化时属性名变成了没有is,导致获取不到值
- 为什么使用序列化
- 序列化是一种对象持久化的手段
- 当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
- 为什么POJO类中要定义为封装类 而不是基本类型
- 封装类在面对null值的时候会报错 ,而基础类型不报错,导致如果数据为null 基础类型会显示为0 不产生异常 难以发现问题
- 为什么禁止修改serialVersionUID
- Serializable 和 Externalizable类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的
- 一旦类实现了 Serializable,就建议明确的定义一个 serialVersionUID。不然在修改类的时候,就会发生异常。
- 组合和聚合的区别
- 组合A类的构造方法里创建B类的对象,也就是说,当A类的一个对象产生时,B类的对象随之产生,当A类的这个对象消亡时,它所包含的B类的对象也随之消亡。
- 聚合A类的对象在创建时不会立即创建B类的对象,而是等待一个外界的对象传给它传给它的这个对象不是A类创建的。