Java泛型报错:T无法转换为String,Google Tink加解密代码复用问题
问题解决步骤
根因分析
- 泛型方法
getInformation直接将未知类型的泛型参数T赋值给boolean/double/String等具体类型变量,没有做类型转换,自然触发类型不兼容报错。 - 逻辑错误:加密后的
encryptedAccInformation栈存储的是密文字节数组,无法直接用于构造明文Account对象,原加密方法末尾调用getInformation传入加密栈属于无效逻辑。 - API误用:
Stack.empty()是判断栈是否为空的方法,返回布尔值,无法清空栈,会导致旧数据残留。
修改方案
1. 改造泛型getInformation方法,增加类型转换参数
通过传入转换函数,兼容不同类型的栈元素转字符串的需求,实现代码复用:
import java.util.function.Function; private <T> Account getInformation(Stack<T> stack, Function<T, String> typeConverter) { // 直接pop不需要先peek再pop,简化代码 boolean isApproved = Boolean.parseBoolean(typeConverter.apply(stack.pop())); boolean isAdmin = Boolean.parseBoolean(typeConverter.apply(stack.pop())); double balance = Double.parseDouble(typeConverter.apply(stack.pop())); String password = typeConverter.apply(stack.pop()); String iBan = typeConverter.apply(stack.pop()); String uuid = typeConverter.apply(stack.pop()); return new Account(uuid, iBan, password, balance, isAdmin, isApproved); }
2. 修正加密方法逻辑
// 加密方法不需要返回Account,加密后的数据存在encryptedAccInformation栈即可,可按需调整返回值 public void encrypt(Account account) throws GeneralSecurityException { // 清空栈用clear(),不要用empty() this.plaintextAccInformation.clear(); this.encryptedAccInformation.clear(); agjEncryption = new AesGcmJce(key.getBytes()); this.plaintextAccInformation.push(account.getUuid()); this.plaintextAccInformation.push(account.getIban()); this.plaintextAccInformation.push(account.getPassword()); this.plaintextAccInformation.push(String.valueOf(account.getBalance())); this.plaintextAccInformation.push(String.valueOf(account.isAdmin())); this.plaintextAccInformation.push(String.valueOf(account.isApproved())); // 去掉多余的iterator,直接判空循环即可 while (!plaintextAccInformation.isEmpty()) { encryptedAccInformation.push(agjEncryption.encrypt(plaintextAccInformation.pop().getBytes(), aad.getBytes())); } // 删掉原来错误的getInformation调用,加密栈无法构造明文Account }
3. 修正解密方法调用
public Account decrypt() throws GeneralSecurityException { this.decryptedAccInformation.clear(); this.agjDecryption = new AesGcmJce(key.getBytes()); while (!encryptedAccInformation.isEmpty()) { decryptedAccInformation.push(new String(agjDecryption.decrypt(encryptedAccInformation.pop(), aad.getBytes()))); } // String类型栈传入identity函数直接返回原值即可 return getInformation(this.decryptedAccInformation, Function.identity()); }
可选扩展:从明文栈构造Account
如果需要直接读取明文栈生成Account,调用方式如下:
Account plainAccount = getInformation(plaintextAccInformation, Function.identity());
内容的提问来源于stack exchange,提问作者Z-100
相关产品推荐
相关产品推荐

