# 实用的类及注解解析
# 一.字符串类
# 1.StringJoiner
# 依赖:
StringJoiner是来自JDK1.8的类,这个类,是封装了StringBuilder.对于拼接字符串更加便捷.
# 用法:
//一个参数,分割符,在add的字符串间拼接.
StringJoiner sj = new StringJoiner("-");
sj.add("1").add("2").add("3");//很容易得到了"1-2-3"
//后面的两个参数,一个是前缀,一个事后缀
StringJoiner sj = new StringJoiner("-","(",")");
sj.add("1").add("2").add("3");//可以得到"(1-2-3)"
//实用案例,,拼接sql的in
StringJoiner sj = new StringJoiner("','","(",")");
for(List<ids>){
sj.add(id);
}
//即可得到 ('id1','id2','id3'.....)
# 说明:
依赖StringBuilder实现,性能和StringBuilder差不多,同样也是非线程安全的
# 二.集合类
# 三.工具类
# 一.Spring.
# 二.lombok
让你的简单的POJO不在需要写冗长的代码也可以达到相同的目的.
# 使用方法:
- 编译器安装lombok插件,这是为了让编译器认识.
- 项目引入依赖.这是为了编译不报错.
# 注解详细介绍.
@Getter,Setter
就是给你生成get,set方法.
@Getter @Setter private boolean employed = true; @Setter(AccessLevel.PROTECTED) private String name; //上面的生成class后就等于 private boolean employed = true; private String name; public boolean isEmployed() { return employed; } public void setEmployed(final boolean employed) { this.employed = employed; } protected void setName(final String name) { this.name = name; }
@NonNull
可以在set的时候帮你判断属性非空,并且是空的话,抛出属性的NullPoint异常.
@Getter @Setter @NonNull private List<Person> members;
Exception in thread "main" java.lang.NullPointerException: members is marked non-null but is null
@ToString
用来生成toString方法,所有的非static字段都会包括,
也可以使用参数exclude来指定需要排除包含的字段,
使用of参数指定需要输出的字段。
通过设置参数callSuper为true,可以将父类的toString输出包含进来。
//是否需要将父类的也ToString,并且可以设置排除哪些字段. @ToString(callSuper=true,exclude="someExcludedField") public class Foo extends Bar { private boolean someBoolean = true; private String someStringField; private float someExcludedField; }
@EqualsAndHashCode
用来生成类的equals和hashcode方法。默认情况下,所有的非static字段和非临时字段都会包含。也可以使用exclude来排除和of来指定包含的字段。callSuper将在两个函数中调用父类中对应的函数。但equals函数必须注意instance类型比较。若只是比较类型是否相同没问题,若比较是不是等于特定类型则可能出问题。若类只是扩展自Object类,不能使用callSuper,会抛出异常。
@EqualsAndHashCode(callSuper=true,exclude={"address","city","state","zip"}) public class Person extends SentientBeing { enum Gender { Male, Female } @NonNull private String name; @NonNull private Gender gender; private String ssn; private String address; private String city; private String state; private String zip; } = public class Person extends SentientBeing { enum Gender { /*public static final*/ Male /* = new Gender() */, /*public static final*/ Female /* = new Gender() */; } @NonNull private String name; @NonNull private Gender gender; private String ssn; private String address; private String city; private String state; private String zip; @java.lang.Override public boolean equals(final java.lang.Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() != this.getClass()) return false; if (!super.equals(o)) return false; final Person other = (Person)o; if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false; if (this.gender == null ? other.gender != null : !this.gender.equals(other.gender)) return false; if (this.ssn == null ? other.ssn != null : !this.ssn.equals(other.ssn)) return false; return true; } @java.lang.Override public int hashCode() { final int PRIME = 31; int result = 1; result = result * PRIME + super.hashCode(); result = result * PRIME + (this.name == null ? 0 : this.name.hashCode()); result = result * PRIME + (this.gender == null ? 0 : this.gender.hashCode()); result = result * PRIME + (this.ssn == null ? 0 : this.ssn.hashCode()); return result; } }
Data
等价于@ToString, @EqualsAndHashCode, @RequiredArgsConstructor, @Getterand@Setter的组合。同时也会生成public的constructor,参数为所有@NonNull 或final的字段。提供参数staticConstructor并指定函数名,会将constructor变为private并生成静态的factory方法。
Cleanup
声明用来确保分配的资源被释放。当局部变量使用其声明,会生成try/finally来保证cleanup函数一定会被调用。默认认为cleanup方法名为close,可以使用value参数来指定函数名。但cleanup函数抛出的异常会覆盖其他的异常(因为在finally中抛出异常),会导致不能找到真正的原因。
public void testCleanUp() { try { @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(new byte[] {'Y','e','s'}); System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); } } == public void testCleanUp() { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { baos.write(new byte[]{'Y', 'e', 's'}); System.out.println(baos.toString()); } finally { baos.close(); } } catch (IOException e) { e.printStackTrace(); } }
@Synchronized
加锁
private DateFormat format = new SimpleDateFormat("MM-dd-YYYY"); @Synchronized public String synchronizedFormat(Date date) { return format.format(date); } == private final java.lang.Object $lock = new java.lang.Object[0]; private DateFormat format = new SimpleDateFormat("MM-dd-YYYY"); public String synchronizedFormat(Date date) { synchronized ($lock) { return format.format(date); } }
@NoArgsConstructor
will generate a constructor with no parameters.
生成没有参数的构造方法.若因为存在final field,则不可能创建没有参数的constructor。@NoArgsConstructor(force = true)将所有的final field用0/false/null初始化。
@RequiredArgsConstructor
为所有未初始化的final字段和@NonNull标注的字段作为参数创建constructor。
@AllArgsConstructor
全参数的构造方法.
@Slf4j
用来在被声明的类中logger变量,如下:
private final Logger logger = LoggerFactory.getLogger(XXX.class);
@Builder
toBuilder参数将提供将对象改为builder对象的功能。具体来说就是你创建了一个对象,其中有某些属性无法使用builder注入,那么可以先使用setter注入然后使用toBuilder()函数获取该对象的builder继续用builder注入其他属性。
//假如有如下的DTO @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public class Dto { @NonNull //status,必选, 执行结果: 0:失败;1:成功; private int status; //data,非必选 类型Array,业务放自定义结果集字段 private Object[] data; //其他n个属性. } //那么在创建时候就可以使用如下方法创建对象. Dto dto = Dto.builder().status(status).data(dataArr).build(); //需要注意!!! //如果只用了Builder注解,对象是无法通过new创建的,必须加上全参数注解和无参数注解,缺一不可.
# 三.ObjectMapper
注意,对象转出来的Map默认是LinkedHashMap
依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.3</version>
</dependency
# 0.引入或注入
public static ObjectMapper mapper = new ObjectMapper();
@Autowired
ObjectMapper objectMapper;
# 1.对象与json串之间的转换
public void testObj() throws JsonGenerationException, JsonMappingException, IOException {
User user = new User(1, "Hello World", new Date());
// 还可以修改时间格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
mapper.writeValue(new File("D:/test.txt"), user); // 写到文件中
// mapper.writeValue(System.out, user); //写到控制台
String jsonStr = mapper.writeValueAsString(user);
System.out.println("对象转为字符串:" + jsonStr);
byte[] byteArr = mapper.writeValueAsBytes(user);
System.out.println("对象转为byte数组:" + byteArr);
User userDe = mapper.readValue(jsonStr, User.class);
System.out.println("json字符串转为对象:" + userDe);
User useDe2 = mapper.readValue(byteArr, User.class);
System.out.println("byte数组转为对象:" + useDe2);
}
# 2.list集合与json字符串
public void testList() throws JsonGenerationException, JsonMappingException, IOException {
List<User> userList = new ArrayList<>();
userList.add(new User(1, "aaa", new Date()));
userList.add(new User(2, "bbb", new Date()));
userList.add(new User(3, "ccc", new Date()));
userList.add(new User(4, "ddd", new Date()));
String jsonStr = mapper.writeValueAsString(userList);
System.out.println("集合转为字符串:" + jsonStr);
List<User> userListDes = mapper.readValue(jsonStr, List.class);
System.out.println("字符串转集合:" + userListDes);
}
# 3.map转json串,字符串转map
public void testMap() {
Map<String, Object> testMap = new HashMap<>();
testMap.put("name", "merry");
testMap.put("age", 30);
testMap.put("date", new Date());
testMap.put("user", new User(1, "Hello World", new Date()));
try {
String jsonStr = mapper.writeValueAsString(testMap);
System.out.println("Map转为字符串:" + jsonStr);
try {
Map<String, Object> testMapDes = mapper.readValue(jsonStr, Map.class);
System.out.println("字符串转Map:" + testMapDes);
} catch (IOException e) {
e.printStackTrace();
}
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
# 4. List<Object>
之间互相转换
public List<XDTO> toXDto(List<PDto> projects){
if(ListUtil.isEmpty(projects)){
return Collections.emptyList();
}
CollectionType type = objectMapper.getTypeFactory().constructCollectionType(List.class,XDTO.class);
//CollectionType type = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class,XDTO.class);
return objectMapper.convertValue(projects, listType);
}
# 5.json字符串转Map数组List<Map<String,Object>>
String expected="[{\"a\":12},{\"b\":23},{\"name\":\"Ryan\"}]";
CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, Map.class);
List<Map<String,Object>> userMapList = mapper.readValue(expected, listType);
# 6. json字符串转对象数组List<Object>
String expected="[{\"a\":12},{\"b\":23},{\"name\":\"Ryan\"}]";
CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, User.class);
List<User> userList = mapper.readValue(expected, listType);
# 7.List<Map<String,Object>>
与List<Object>
互相转换
//List<Obj>转List<Map>
List<Menu> menuList=menuDAOImpl.findByParentId(parentId);
return objectMapper.convertValue(menuList,new TypeReference<List<Map<String, Object>>>(){});
//测试用例
List<StaffDto> staffList = new ArrayList<StaffDto>() {{
StaffDto staffDto = new StaffDto();
staffDto.setCode("111");
staffDto.setDeptName("yi 部门");
add(staffDto);
}};
List<Map<String, Object>> resList = objectMapper.convertValue(staffList, new TypeReference<List<Map<String, Object>>>() {});
System.out.println(resList);
//转List<Obj>
List<Map<String,Object>> menuList= menuDAOImpl.findByParentId(parentId);
return objectMapper.convertValue(menuList, new TypeReference<List<Menu>>(){});
//测试用例
List<Map<String, Object>> staffListmap = new ArrayList<Map<String, Object>>() {{
Map<String, Object> map = new HashMap<>();
map.put("code", "111");
map.put("deptName", "yi bumen ");
add(map);
}};
List<StaffDto> staffListObj = objectMapper.convertValue(staffListmap, new TypeReference<List<StaffDto>>() {});
System.out.println(staffListObj);