# 实用的类及注解解析

# 一.字符串类

# 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插件,这是为了让编译器认识.
  • 项目引入依赖.这是为了编译不报错.

# 注解详细介绍.

  1. @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;
    }
    
  2. @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

  3. @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;
    }
    
  4. @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;
            }
        }
    
    
  5. Data

    等价于@ToString, @EqualsAndHashCode, @RequiredArgsConstructor, @Getterand@Setter的组合。同时也会生成public的constructor,参数为所有@NonNull 或final的字段。提供参数staticConstructor并指定函数名,会将constructor变为private并生成静态的factory方法。

  6. 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();
            }
        }
    
  7. @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);
            }
        }
    
  8. @NoArgsConstructor

    will generate a constructor with no parameters.

    生成没有参数的构造方法.若因为存在final field,则不可能创建没有参数的constructor。@NoArgsConstructor(force = true)将所有的final field用0/false/null初始化。

  9. @RequiredArgsConstructor

    为所有未初始化的final字段和@NonNull标注的字段作为参数创建constructor。

  10. @AllArgsConstructor

    全参数的构造方法.

  11. @Slf4j

    用来在被声明的类中logger变量,如下:

    private final Logger logger = LoggerFactory.getLogger(XXX.class);
    
  12. @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);