1.影响Servlet生命周期的注解:@PostConstruct和@PreDestroy
@PostConstruct:被修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的init()方法.注:方法会在构造函数之后,init()方法之前运行.
@PreDestroy:被修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似与Servlet的destroy()方法.注:方法会在destroy()方法之后,彻底卸载前运行.
2.JVM垃圾回收小结
Java虚拟机将堆分为新生代和老年代,并且对不同代采用不同的垃圾回收算法。其中,新生代分为Eden区和两个大小一致的Survivor区,并且其中一个Survivor区是空的(默认情况下,JVM采用一种动态分配的策略,对应VM参数为-XX:+UserPSAdaptiveSurvivorSizePolicy,根据生成对象的速率,以及Survivor区的使用情况动态调整Eden区和Survivor区的比例)。
在只针对新生代的MinorGC中,Eden区和非空Survivor区的存活对象会被复制到空的Survivor区中,当Survivor区中的存活对象复制次数超过一定数量时(对应VM参数:-XX:+MaxTenuringThreshold),那么该对象将被晋升至老年代;另外,如果单个Survivor区已经被占用了50%(对应虚拟机参数 -XX:TargetSurvivorRatio),那么较高复制次数的对象也会被晋升(promote)至老年代。
因为Minor GC只针对新生代进行垃圾回收,所以在枚举GC Roots的时候,它需要考虑从老年代到新生代的引用。为了避免扫描整个老年代,Java虚拟机引入了名为卡表(Card Table)的技术,大致的标出可能存在老年代到新生代引用的内存区域。
3.File转MultipartFile
有时候做接口测试,处理前端上传的文件,这时可采用此方法,将本地文件转为上传文件类型 MultipartFile ,代码如下:
importjava.io.File;importjava.io.FileInputStream;importorg.springframework.web.multipart.MultipartFile;importorg.springframework.mock.web.MockMultipartFile;
File pdfFile= new File("/home/nya/data/images/10000.jpg");
FileInputStream fileInputStream= newFileInputStream(pdfFile);
MultipartFile multipartFile= newMockMultipartFile(pdfFile.getName(), pdfFile.getName(),"", fileInputStream);
4.@Deprecated @SuppressWarning @Override
Java注解annotation,作为被javac识别的一种标识,此处简述三种常见注解的意义表述
@Deprecated 过时的
@SuppressWarning 抑制警告
@Override 覆盖
@Deprecated 过时API注解 我们在用到JDK提供的API的时候,在编译中遇到 这样的提示 提示用到过时的API ,那么这个API 就被这个 @Deprecated注解所 标识,在javac进行编译的时候 发现了注解便做出相应的提示 。
@SuppressWarning("deprecation") 从字面意思上就是抑制 过时API的警告 ,这个可以放在调用过时的API的方法外部或者调用方法之前,那么在编译的时候 javac遇到这个标识 即使知道API过时那么也不会输出过时API的提示
@Override 这个是覆盖注解 ,也就是在继承中进行覆盖 父类的某个方法的时候可以加上这个注解 ,加上这个注解之后 如果我们的覆盖方法 出错了 Eclipse会提示我们错误
源码示例:
参见netty源码 : io.netty.channel.ChannelInboundHandler/**
* Gets called if a {@link Throwable} was thrown.*/@Override
@SuppressWarnings("deprecation")void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
999.代码可读性规范与优化
1、Integer的equals方法
实际开发中,基本类型的包装类使用的更多,相关的操作方法也是量级递增,这时在方法选择上 包装类 --> commons.util --> 工具类 的优先级选择顺序。
此处以两个int类型的比较为例
int a = 1;int b = 1;if ( a ==b ) ...if ( a !=b ) ...
Integer a= 2;
Integer b= 2;if( a.equals(b)) ...if ( !a.equals(b)) ...
2、stream的map使用
Java8引入的数据流Stream API,是Java在代码可读性上的一大突破。使得传统的数据流操作更加fluent。这里用作类型转换map方法愈加使得Stream调度富有变化,搭配lambda表达式更多了一种别样的美感。
而在实际使用中, -> 也推荐由 :: 替代使用,示例如下:
//基本类型转字符串
list.stream().map(item -> item.toString()).collect(Collectors.toList()); //不推荐
list.stream().map(Object::toString).collect(Collectors.toList());//本地工具类方法的调度,以数据类型转md5为例
list.stream().map(item -> Md5Utils.md5(item)).collect(Collectors.toList()); //不推荐
list.stream().map(Md5Utils::md5).collect(Collectors.toList());
注意:上例更多的适用于实体类中getXXX()的使用。***
Stream API的确给代码的编写赋予了许多便利,但一些基本的用法也是经典,一味的为了生套反而丧失了代码本身的可读性。以集合类型转换为例。
//以多线程处理常用的线程安全且多线程执行的高效队列ConcurrentLinkedDeque为例
ConcurrentLinkedDeque queue = new...;
List list = queue.stream().collect(Collectors.toList()); //尽量避免
List list = new ArrayList<>(queue);
由上可知,代码编写精炼反而赋予了更高的可读性,尽量避免脱裤子放屁,如下:
//循环中操作参数Map,为避免迭代中参数的变更,需在循环体中重新构建映射,此时只需作为带参构造获取新的Map即可
Map nowMap = new HashMap<>();
nowMap.putAll(paramMap);//避免
Map nowMap = new HashMap<>(paramMap);