跳至主要內容

泛型

chanchaw大约 2 分钟languagejava

案例

运行时具体类型

获取调用时传入的类型后可以创建实例对象,获取类型的属性,通过反射调用类型的方法,具体使用见仓库 https://gitee.com/chanchaw/my-orm 的类 MBBaseServiceImpl

public class MBBaseServiceImpl<T> implements BaseService<T> {

    @Autowired
    private BaseMapper mapper;

    @Override
    public List<T> queryList(Object obj) throws InvocationTargetException, IllegalAccessException, SQLException, InstantiationException {
        final ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
        Class<T> modelClass = (Class<T>)type.getActualTypeArguments()[0];
        // 上面的 modelClass 是调用类 MBBaseServiceImpl 时传入的具体类型
	    // 使用本类型可以创建对应的实例对象
        T newRecord = modelClass.newInstance();
        // 也可以获取类型拥有的属性,然后通过反射调用 getter,setter 方法
        Field[] fields = modelClass.getDeclaredFields();


    // 下面是小驼峰模式下,获取 getter,setter 方法名称
    public static String getGetterMethodName(Object obj,Field field){
        String fieldName = field.getName();
        return "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
    }

    public static String getSetterMethodName(Field field){
        return "set" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
    }

泛型方法

public static <T> T removeObjNoSentidoAndBlank(T record){
    // 通过反射遍历属性,处理所有字符串类型的属性
    Class<?> aClass = record.getClass();
    Field[] declaredFields = aClass.getDeclaredFields();
    for(Field item:declaredFields){
        item.setAccessible(true);
        boolean b = item.getGenericType().toString().equalsIgnoreCase("class java.lang.String");
        if(b){
            try {
                String strVal = (String)item.get(record);
                strVal = StringUtils.removeNoSentidoAndBlank(strVal);
                item.set(record,strVal);
            } catch (IllegalAccessException e) {
                System.out.println("移除对象["+record+"]的属性["+item.getName()+"]的回车换行符时出现异常!");
            }
        }
    }

    return record;
}

泛型参数的类类型

下面方法通过第三个参数传入泛型的类类型同时返回该泛型的对象

package com.xdf.wxpad.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.Map;

/**
 * @author chanchaw
 * @create 2024-09-02 8:58
 */
@Component
public class RestTemplateUtils {
    @Resource
    private RestTemplate restTemplate;

    public <T> T postJson(String url, Map<String, Object> param, Class<T> responseType) throws JsonProcessingException {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        ObjectMapper mapper = new ObjectMapper();
        ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
        String paramJsonString = ow.writeValueAsString(param);

        HttpEntity<String> formEntity = new HttpEntity<>(paramJsonString, headers);
        String responseJsonString = restTemplate.postForObject(url, formEntity, String.class);

        return mapper.readValue(responseJsonString, responseType);
    }
}

// 调用方法
CallTemplateMsgRes callRes = restTemplateUtils.postJson(reqUrl, BeanMap.create(msg), CallTemplateMsgRes.class);

下面将上面案例简化

public <T> T get4Object(String url, Class<T> responseType) {
    return restTemplate.getForObject(url, responseType);
}

// 获取 String 类型的响应
String url = "http://example.com";
String response = get4Object(url, String.class);

// 获取 Integer 类型的响应
Integer intResponse = get4Object(url, Integer.class);