You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将派生类对象传入基类引用参数,如何获取完整派生类属性?

问题描述

现有基类User及两个派生类Admin和Manager,代码如下:

基类 - User

public class User {
    public String userId;
    public String name;
    public String type;
}

派生类 - Admin

public class Admin extends User {
    public String prop1;
    public String prop2;
}

派生类 - Manager

public class Manager extends User {
    public String prop3;
    public String prop4;
}

基类包含Admin和Manager共享的通用属性。当前有一个调用API创建用户的方法,可用于创建不同类型的用户,代码如下:

public class Response<T>{
     public int statusCode;
     public T result;
}

public class UserCreation{
   public static void main(String[] args){
     RequestHandler requestHandler = new RequestHandler();
     User userRequest = requestHandler.createUserCreationRequest("Admin");
     UserCreationDao.createUser(userRequest);

     User userRequest = requestHandler.createUserCreationRequest("Manager");
     UserCreationDao.createUser(userRequest);
  }
}

public class RequestHandler{
    public User createUserCreationRequest(String userType) {
        switch (userType) {
            case "Admin":
                return createAdminRequest();
            case "Manager":
                return createManagerRequest();
            default:
                throw new IllegalArgumentException("Invalid processor");
        }
    }

    private Admin createAdminRequest(){
        Admin admin = new Admin();
        admin.setName("Admin");
        admin.setType("Admin");
        admin.setProp1("prop1");
        admin.setProp2("prop2");
        return admin;
    }

    private Manager createManagerRequest(){
        Manager manager = new Manager();
        manager.setName("Manager");
        manager.setType("Manager");
        manager.setProp3("prop2");
        manager.setProp4("prop3");
        return manager;
    }
}

public class UserCreationDao{
    public void createUser(User userRequest) {
        Response<User> response = userapi.createuser(HttpMethod.POST, "/users", userRequest, new ParameterizedTypeReference<Response<User>>() {}, key);
    }
}

当前问题:执行UserCreationDao的createUser方法时,Response对象的result属性本应填充派生类(Admin或Manager)的完整信息,但由于指定了Response<User>类型,无法返回Admin和Manager的全部属性。希望仍使用同一个方法,让Response对象根据传入的派生类,填充对应派生类的完整属性到result中。

可行解决方案

方案1:泛型化createUser方法

将UserCreationDao的createUser方法改为泛型方法,利用Java的类型推断动态生成ParameterizedTypeReference,确保反序列化时能识别传入的实际派生类类型。

修改后的UserCreationDao代码:

public class UserCreationDao{
    public <T extends User> void createUser(T userRequest) {
        ParameterizedTypeReference<Response<T>> typeRef = new ParameterizedTypeReference<Response<T>>() {};
        Response<T> response = userapi.createuser(HttpMethod.POST, "/users", userRequest, typeRef, key);
        // 此时response.result为对应Admin/Manager实例,包含所有派生类属性
    }
}

同时修正UserCreation中的重复变量名问题,并优化类型获取(可避免强制转换):

public class UserCreation{
   public static void main(String[] args){
     RequestHandler requestHandler = new RequestHandler();
     Admin adminRequest = (Admin) requestHandler.createUserCreationRequest("Admin");
     UserCreationDao.createUser(adminRequest);

     Manager managerRequest = (Manager) requestHandler.createUserCreationRequest("Manager");
     UserCreationDao.createUser(managerRequest);
  }
}

进一步优化RequestHandler为泛型方法,省去强制转换:

public class RequestHandler{
    @SuppressWarnings("unchecked")
    public <T extends User> T createUserCreationRequest(String userType) {
        switch (userType) {
            case "Admin":
                return (T) createAdminRequest();
            case "Manager":
                return (T) createManagerRequest();
            default:
                throw new IllegalArgumentException("Invalid processor");
        }
    }

    // 原createAdminRequest、createManagerRequest方法保持不变
}

调用时可直接获取对应类型:

Admin adminRequest = requestHandler.createUserCreationRequest("Admin");
Manager managerRequest = requestHandler.createUserCreationRequest("Manager");

方案2:显式传递类型令牌

如果泛型类型推断不够灵活,可在调用时传入派生类的Class对象,自定义ParameterizedTypeReference来指定具体的反序列化类型。

修改UserCreationDao的方法:

public class UserCreationDao{
    public <T extends User> void createUser(T userRequest, Class<T> userClass) {
        ParameterizedTypeReference<Response<T>> typeRef = new ParameterizedTypeReference<Response<T>>() {
            @Override
            public Type getType() {
                return new ParameterizedType() {
                    @Override
                    public Type[] getActualTypeArguments() {
                        return new Type[]{userClass};
                    }

                    @Override
                    public Type getRawType() {
                        return Response.class;
                    }

                    @Override
                    public Type getOwnerType() {
                        return null;
                    }
                };
            }
        };
        Response<T> response = userapi.createuser(HttpMethod.POST, "/users", userRequest, typeRef, key);
    }
}

调用示例:

Admin adminRequest = (Admin) requestHandler.createUserCreationRequest("Admin");
UserCreationDao.createUser(adminRequest, Admin.class);

Manager managerRequest = (Manager) requestHandler.createUserCreationRequest("Manager");
UserCreationDao.createUser(managerRequest, Manager.class);

方案3:利用序列化框架的多态支持

如果API返回的响应中包含type字段(如"type": "Admin"),可配置JSON序列化框架(如Jackson),让其根据该字段自动反序列化为对应的派生类。

以Jackson为例,在基类User上添加注解:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type"
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Admin.class, name = "Admin"),
    @JsonSubTypes.Type(value = Manager.class, name = "Manager")
})
public class User {
    public String userId;
    public String name;
    public String type;
}

此时即使声明Response<User>,Jackson也会根据type字段自动将result反序列化为对应的Admin或Manager实例,包含所有派生类属性,无需修改业务方法逻辑。


内容的提问来源于stack exchange,提问作者YNP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 02:06:35