class.cast方法castexception是什么异常

> Spring使用AOP时ClassCastException有关问题
Spring使用AOP时ClassCastException有关问题
xj_shenbin & &
发布时间: & &
浏览:130 & &
回复:0 & &
悬赏:0.0希赛币
Spring使用AOP时ClassCastException问题
Spirng实现AOP采用动态代理还是CGLIB代理,两种方式如下:1、Spring:自动选择。如果有实现接口采用JDK动态代理如果没有实现接口采用cglib代理  &aop:aspectj-autoproxy proxy-target-class="false"/&
2、强制只用cglilb代理:  &aop:aspectj-autoproxy proxy-target-class="true"/&
以下是JDK动态代理和CGLIB代理简单介绍&&& JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。&&& CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。注意:cglib代理不能覆盖 final 方法! 在final方法前面后面加逻辑不行。在默认情况下,如果一个目标对象如果实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出j ava.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类,不会有ClassCastException异常以下为网上摘录的:Spring AOP部分使用JDK动态代理或者CGLIB来为目标对象创建代理。(建议尽量使用JDK的动态代理)如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理。如果你希望强制使用CGLIB代理,(例如:希望代理目标对象的所有方法,而不只是实现自接口的方法)那也可以。但是需要考虑以下问题:&&& * 无法通知(advise)Final 方法,因为他们不能被覆写。&&& * 你需要将CGLIB 2二进制发行包放在classpath下面,与之相较JDK本身就提供了动态代理强制使用CGLIB代理需要将 &aop:config& 的 proxy-target-class 属性设为true:&aop:config proxy-target-class="true"&...&/aop:config&当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 &aop:aspectj-autoproxy& 的 proxy-target-class 属性:&aop:aspectj-autoproxy proxy-target-class="true"/&而实际使用的过程中才会发现细节问题的差别,The devil is in the detail.JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理。CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强。Spring是依靠什么来判断采用哪种代理策略来生成AOP代理呢?以下代码就是Spring的判断逻辑  //org.springframework.aop.framework.DefaultAopProxyFactory
//参数AdvisedSupport 是Spring AOP配置相关类
public AopProxy createAopProxy(AdvisedSupport advisedSupport)
throws AopConfigException {
//在此判断使用JDK动态代理还是CGLIB代理
if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(advisedSupport)) {
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. "
+ "Add CGLIB to the class path or specify proxy interfaces.");
return CglibProxyFactory.createCglibProxy(advisedSupport);
return new JdkDynamicAopProxy(advisedSupport);
}advisedSupport.isOptimize()与advisedSupport.isProxyTargetClass()默认返回都是false,所以在默认情况下目标对象有没有实现接口决定着Spring采取的策略,当然可以设置advisedSupport.isOptimize()或者advisedSupport.isProxyTargetClass()返回为true,这样无论目标对象有没有实现接口Spring都会选择使用CGLIB代理。所以在默认情况下,如果一个目标对象如果实现了接口Spring则会选择JDK动态代理策略动态的创建一个接口实现类(动态代理类)来代理目标对象,可以通俗的理解这个动态代理类是目标对象的另外一个版本,所以这两者之间在强制转换的时候会抛出java.lang.ClassCastException。而所以在默认情况下,如果目标对象没有实现任何接口,Spring会选择CGLIB代理, 其生成的动态代理对象是目标类的子类。上说的是默认情况下,也可以手动配置一些选项使Spring采用CGLIB代理。org.springframework.transaction.interceptor.TransactionProxyFactoryBean是org.springframework.aop.framework. ProxyConfig的子类,所以可以参照ProxyConfig里的一些设置如下所示,将optimize和proxyTargetClass任意一个设置为true都可以强制Spring采用CGLIB代理。如果当需要使用CGLIB代理和@AspectJ自动代理支持,请按照如下的方式设置 &aop:aspectj-autoproxy& 的 proxy-target-class 属性:&aop:aspectj-autoproxy proxy-target-class="true"/&这样使用CGLIB代理也就不会出现前面提到的ClassCastException问题了,也可以在性能上有所提高,关键是对于代理对象是否继承接口可以统一使用。Spring doc原文解释如下:optimization will usually mean that advice changes won't& take effect after a proxy has been created. For this reason, optimization& is disabled by default。
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&46874人阅读
102 Java Web技术(55)
ClassCastException,从字面上看,是类型转换错误,通常是进行强制类型转换时候出的错误。下面对产生ClassCastException异常的原因进行分析,然后给出这种异常的解决方法。
这种异常是如何产生的呢?举一个比较形象的例子。
Animal表示动物,Dog表示狗,是动物的子类,Cat表示猫,是动物的子类。看下面的代码:
Animal a1 = new Dog();& // 1
Animal a2 = new Cat();& // 2
Dog d1 = (Dog)a1;&&&&&&&& //3
Dog d2 = (Dog)a2;&&&&&&& //4
第3行代码和第4行代码基本相同,从字面意思看都是把动物(Animal)强制转换为狗(Dog),但是第4行代码将产生java.lang.ClassCastException。原因是你要把一个猫(a2这只动物是猫)转换成狗,而第3行中是把狗转换成狗,所以可以。
从上面的例子看,java.lang.ClassCastException是进行强制类型转换的时候产生的异常,强制类型转换的前提是父类引用指向的对象的类型是子类的时候才可以进行强制类型转换,如果父类引用指向的对象的类型不是子类的时候将产生java.lang.ClassCastException异常。就是上面a1和a2都是动物,但是a1这只动物是一只狗,而a2这只动物是猫,所以要把a1转换成狗可以,因为a1本身就是狗,而a2是一只猫,所以要转换成狗就出错了。
遇到这样的异常的时候如何解决呢?如果你知道要访问的的对象的具体类型,直接转换成该类型即可。如果不能确定类型可以通过下面的两种方式进行处理(假设对象为o):
1、通过o.getClass().getName()得到具体的类型,可以通过输出语句输出这个类型,然后根据类型进行进行具体的处理。
2、通过if(o instanceof 类型)的语句来判断o的类型是什么。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1207037次
积分:16558
积分:16558
排名:第397名
原创:304篇
评论:3217条
(1)(3)(1)(2)(2)(5)(2)(1)(22)(21)(11)(6)(9)(22)(15)(15)(35)(21)(23)(2)(1)(5)(4)(4)(1)(2)(8)(1)(6)(4)(14)(5)(12)(12)(5)(13)ClassCastException是如何产生的(1)
======================================如何产生ClassCastException:======================================ClassCastException是JVM在检测到两个类型间转换不兼容时引发的运行时异常。此类错误通常会终止用户请求。在执行任何子系统的应用程序代码时都有可能发生ClassCastException异常。通过转换,可以指示Java编译器将给定类型的变量作为另一种变量来处理。对基础类型和用户定义类型都可以转换。Java语言规范定义了允许的转换,其中大多数可在编译时进行验证。不过,某些转换还需要运行时验证。如果在此运行时验证过程中检测到不兼容,JVM就会引发ClassCastException异常。例如:FApple a = (Apple)f;当出现下列情况时,就会引发ClassCastException异常:1.Fruit和Apple类不兼容。当应用程序代码尝试将某一对象转换为某一子类时,如果该对象并非该子类的实例,JVM就会抛出ClassCastException异常。java.lang.ClassCastException: com.tools.classloader.data.HelloWorld incompatible with com.tools.classloader.HelloWorld&&& at com.tools.classloader.data.DifferentClassLoader.testClassCastException(DifferentClassLoader.java:77)
2.Fruit和Apple类兼容,但加载时使用了不同的ClassLoader。这是这种异常发生最常见的原因。在这里,需要了解一下什么是ClassLoader?
=====================================================不同的ClassLoader如何产生ClassCastException::=====================================================Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类 com.example.Sample,编译之后生成了字节代码文件 Sample.class。两个不同的类加载器 ClassLoaderA 和 ClassLoaderB 分别读取了这个 Sample.class 文件,并定义出两个 java.lang.Class 类的实例来表示这个类。这两个实例是不相同的。对于 Java 虚拟机来说,它们是不同的类。试图对这两个类的对象进行相互赋值,会抛出运行时异常 ClassCastException。
java.lang.ClassCastException:com.ibm.j2ca.extension.emd.runtime.WBIDataBindingImpl incompatible with com.ibm.ws.sca.binding.j2c.handler.J2CImportHandler.getDataBinding(J2CImportHandler.java:2343)commonj.connector.runtime.DataBinding
----------------------ClassLoader:----------------------ClassLoader是允许JVM查找和加载类的一种Java类。JVM有内置的ClassLoader。不过,应用程序可以定义自定义的ClassLoader。应用程序定义新的ClassLoader通常出于以下两种原因:1.自定义和扩展JVM加载类的方式。例如,增加对新的类库(网络、加密文件等)的支持。2.划分JVM名称空间,避免名称冲突。例如,可以利用划分技术同时运行同一应用程序的多个版本(基于空间的划分)。此项技术在应用服务器(如WebLogic Server)内的另一个重要用途是启用应用程序热重新部署,即在不重新启动JVM的情况下启动应用程序的新版本(基于时间的划分)。ClassLoader按层级方式进行组织。除系统BootClassLoader外,其它ClassLoader都必须有父ClassLoader。在理解类加载的时候,需要注意以下几点:1.永远无法在同一ClassLoader中重新加载类。“热重新部署”需要使用新的ClassLoader。每个类对其ClassLoader的引用都是不可变的:this.getClass().getClassLoader()。2.在加载类之前,ClassLoader始终会先询问其父ClassLoader(委托模型)。这意味着将永远无法重写“核心”类。3.同级ClassLoader间互不了解。4.由不同ClassLoader加载的同一类文件也会被视为不同的类,即便每个字节都完全相同。这是ClassCastException的一个典型原因。5.可以使用Thread.setContextClassLoader(a)将ClassLoader连接到线程的上下文。基于以上的基本原理,可以加深大家对ClassCastException的理解,和在碰到问题时提供一种解决问题的思路。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.edit_contact);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.custom_title);
initVars();
initFields();
private void initVars()
mTitle = (TextView) findViewById(R.id.title);
mName = (EditText) findViewById(R.id.txt_name);
&-----这一行报错 line:56
mMobile = (EditText) findViewById(R.id.txt_mobile);
mHome = (EditText) findViewById(R.id.txt_home);
mEmail = (EditText) findViewById(R.id.txt_email);
mRelation = (EditText) findViewById(R.id.txt_relation);
mBlog = (EditText) findViewById(R.id.txt_blog);
mSave = (Button) findViewById(R.id.btn_save);
mRes = getResources();
&!-- name --&
&LinearLayout android:orientation=&horizontal&
android:layout_margin=&5dip& android:layout_width=&fill_parent&
android:layout_height=&wrap_content&&
&TextView android:layout_width=&0dip& android:layout_height=&wrap_content&
android:layout_weight=&2& android:text=&@string/field_name&&&/TextView&
&EditText android:id=&@+id/txt_name& android:layout_width=&0dip&
android:layout_height=&wrap_content& android:layout_weight=&8&
android:singleLine=&true&&&/EditText&
&/LinearLayout&
E/AndroidRuntime( 1768): Caused by: java.lang.ClassCastException: android.widget.TextViewE/AndroidRuntime( 1768):
at com.uery.contacts.EditContactActivity.initVars(EditContactActivity.java:56)E/AndroidRuntime( 1768):
at com.uery.contacts.EditContactActivity.onCreate(EditContactActivity.java:48)E/AndroidRuntime( 1768):
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)E/AndroidRuntime( 1768):
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)E/AndroidRuntime( 1768):
... 11 more运行的时候,会报如上的错误,明明类型是一样的啊,怎么破!?PS:以前也有过这种情况,不知道怎么的,过一会它自己就好了-v-------解决方案--------------------
project -- & clean ,就好了。
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有}

我要回帖

更多关于 class.cast方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信