gpt4 book ai didi

java - 使用 Plastic 框架进行代码生成时出现棘手的 ClassCastException

转载 作者:行者123 更新时间:2023-12-01 15:21:06 27 4
gpt4 key购买 nike

这是什么意思大家好 - 我正在看一个名为“鱼与熊掌兼得:Java 元编程”的演示文稿

演讲者是 Howard M. Lewis Ship,他是 Tapestry 的作者之一 - 在制作该作品的过程中,创建了一个名为“Plastic ”的子项目来利用 ASM 来改变字节码。

我不会假装自己是专家,但最终结果应该是我可以编写代码,以便可以使用带注释的类、方法和字段来生成进一步的 java 代码,从而减少样板代码。

我的问题下面的代码是演示我的问题的完整示例。测试示例应修改 EqualsDemo 类,使其包含 equals() 和 hashCode() 的实现。运行它时,我收到一个错误,基本上表明我无法将“com.example. Plastic.transformed.EqualsDemo”类型的对象强制转换为“com.example. Plastic.transformed.EqualsDemo”(是的,同一个类) .

演示者刚刚提到这些错误很烦人,但没有提及它们的来源 - 到目前为止我的搜索表明它们与不同的类加载器有关。然而,我完全无法解决这个问题,因此我的问题在这里(!)

com.example.plastic.transformed.EqualsDemo cannot be cast to com.example.plastic.transformed.EqualsDemo
at MainClass.main(MainClass.java:28)

那么我需要做什么?替换类加载器? (如果是这样,怎么办?)或者是否有塑料的某些部分我不明白?为了使事情顺利进行,我需要使用一些用于生成代理对象或类似对象的方法?

PS!到目前为止,我发现的示例在带注释的实例的最终使用中都使用了我认为的 Groovy。

希望有人比我更有能力:)

链接:Tapestry 主页(塑料作为 jar 包含在下载中):http://tapestry.apache.org/

Main.java

import java.util.ArrayList;
import java.util.List;

import org.apache.tapestry5.internal.plastic.StandardDelegate;
import org.apache.tapestry5.plastic.ClassInstantiator;
import org.apache.tapestry5.plastic.PlasticManager;

import com.example.plastic.transformer.EqualsHashCodeTransformer;
import com.example.plastic.transformed.EqualsDemo;

public class MainClass {

public static void main(String[] args) {


List<String> pList = new ArrayList<String>();
pList.add("com.example.plastic.transformed");

PlasticManager pm = PlasticManager
.withContextClassLoader()
.delegate( new StandardDelegate(new EqualsHashCodeTransformer()) )
.packages(pList)
.create();


final String EQUALSDEMO = "com.example.plastic.transformed.EqualsDemo";
ClassInstantiator<EqualsDemo> i = pm.getClassInstantiator(EQUALSDEMO);
i.newInstance().hashCode();
/*
com.example.plastic.transformed.EqualsDemo cannot be cast to com.example.plastic.transformed.EqualsDemo
at MainClass.main(MainClass.java:28)
*/
}
}

实现EqualsHashCode.java

package com.example.plastic.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ImplementEqualsHashCode {

}

EqualsHashCodeTransformer.java

package com.example.plastic.transformer;

import java.util.ArrayList;
import java.util.List;

import org.apache.tapestry5.plastic.FieldHandle;
import org.apache.tapestry5.plastic.MethodAdvice;
import org.apache.tapestry5.plastic.MethodDescription;
import org.apache.tapestry5.plastic.MethodInvocation;
import org.apache.tapestry5.plastic.PlasticClass;
import org.apache.tapestry5.plastic.PlasticClassTransformer;
import org.apache.tapestry5.plastic.PlasticField;

import com.example.plastic.annotations.*;

public class EqualsHashCodeTransformer implements PlasticClassTransformer {
private MethodDescription EQUALS = new MethodDescription("boolean", "equals", "java.lang.Object");

private MethodDescription HASHCODE = new MethodDescription("int", "hashCode");

private static final int PRIME = 37;

public void transform(PlasticClass plasticClass){

//check that the class is annotated
if(!plasticClass.hasAnnotation(ImplementEqualsHashCode.class)) {
return;
}

List<PlasticField> fields = plasticClass.getAllFields();


final List<FieldHandle> handles = new ArrayList<FieldHandle>();
for(PlasticField field : fields){
handles.add(field.getHandle());
}

//HashCode method introduction :)
plasticClass.introduceMethod(HASHCODE).addAdvice(new MethodAdvice() {
public void advise(MethodInvocation invocation){
Object instance = invocation.getInstance();
int result = 1;

for(FieldHandle handle : handles){
Object fieldValue = handle.get(instance);

if(fieldValue != null)
result = (result * PRIME) + fieldValue.hashCode();
}

invocation.setReturnValue(result);

//Don't proceed to the empty introduced method
}

});

plasticClass.introduceMethod(EQUALS).addAdvice(new MethodAdvice() {
public void advise(MethodInvocation invocation) {
Object thisInstance = invocation.getInstance();
Object otherInstance = invocation.getParameter(0);

invocation.setReturnValue(isEqual(thisInstance, otherInstance));

//Don't proceed to the empty introduced method
}

private boolean isEqual(Object thisInstance, Object otherInstance) {

if(thisInstance == otherInstance)
return true;

if(otherInstance == null)
return false;

if(!(thisInstance.getClass() == otherInstance.getClass()))
return false;

for(FieldHandle handle : handles){
Object thisValue = handle.get(thisInstance);
Object otherValue = handle.get(otherInstance);

if(!(thisValue == otherValue || thisValue.equals(otherValue)))
return false;
}

return true;
}
});
}
}

EqualsDemo.java

package com.example.plastic.transformed;

import com.example.plastic.annotations.ImplementEqualsHashCode;


@ImplementEqualsHashCode
public class EqualsDemo {
private int intValue;
private String stringValue;

public int getIntValue(){
return intValue;
}

public void setIntValue(int intValue){
this.intValue = intValue;
}

public String getStringValue(){
return stringValue;
}

public void setStringValue(String stringValue){
this.stringValue = stringValue;
}
}

最佳答案

您不想将包添加到 Plastic 管理器中 - 它使用不同的类加载器并加载这些类,在这些包中制作类的两份副本(一份在父类加载器中,一份在 Plastic 类加载器中) )这会给你当框架尝试转换为你的类时看到的 ClassCastException 。试试这个:

import org.apache.tapestry5.internal.plastic.StandardDelegate;
import org.apache.tapestry5.plastic.ClassInstantiator;
import org.apache.tapestry5.plastic.PlasticManager;

public class MainClass {

public static void main(String[] args) {
PlasticManager pm = PlasticManager
.withContextClassLoader()
.delegate(new StandardDelegate())
.create();
ClassInstantiator<EqualsDemo> ci = pm.createClass(EqualsDemo.class, new EqualsHashCodeTransformer());
System.out.println(ci.newInstance().hashCode());
}
}

关于java - 使用 Plastic 框架进行代码生成时出现棘手的 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10921361/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com