2022.2.13java学习笔记
2022.2.12
其他
2022.2.13
on java 8 (摘錄)
對Class對象使用泛型語法時,newInstance()會返回對象的確切類型,而不僅僅是簡單的Object,就像在ToyTest.java示例中看到的那樣。但它也會受到一些限制:
// reflection/toys/GenericToyTest.java // 測試Class類 // {java reflection.toys.GenericToyTest} package reflection.toys;public class GenericToyTest {public static voidmain(String[] args) throws Exception {Class<FancyToy> ftc = FancyToy.class;// 生成確切的類型:FancyToy fancyToy =ftc.getConstructor().newInstance();Class<? super FancyToy> up = ftc.getSuperclass();// 下面的代碼無法通過編譯:// Class<Toy> up2 = ftc.getSuperclass();// 只能生成ObjectObject obj = up.getConstructor().newInstance();} }如果你得到了基類,那么編譯器只允許你聲明這個基類引用是“FancyToy的某個基類”,就像表達式Class<? super FancyToy>所聲明的那樣。它不能被聲明為Class<Toy>。這看起來有點兒奇怪,因為getSuperclass()返回了基類(不是接口),而編譯器在編譯時就知道這個基類是什么——在這里就是Toy.class,而不僅僅是“FancyToy的某個基類”。不管怎么樣,因為存在這種模糊性,所以up.getConstructor().newInstance()的返回值不是一個確切的類型,而只是一個Object。
這里我是真感覺有意思,因為編譯階段確實應該知道基類的確切類型,而java本身又具有單繼承機制,又不像c++的多繼承會導致編譯器不知道應該選擇哪個基類,令人懵逼,讓我感覺這個機制是不是從c++那里抄過來的,但又沒有將它給融入進java的體系里,讓人感覺另類
Java中還有第三種形式的反射。這就是關鍵字instanceof,它返回一個boolean值,表明一個對象是否是特定類型的實例。
傳統的類型轉換。比如“(Shape)”,它使用反射來確保轉型是正確的。如果你執行了錯誤的轉型,它會拋出一個ClassCastException。
代表對象類型的Class對象。你可以查詢Class對象來獲取有用的運行時信息。
問題
為什么在java在傳統的類型轉化中用到了反射.
簡單反射,它假定你在編譯時就已經知道了所有可用的類型
這是反射最基本的形式,在運行時檢查了所有的類型轉換是否正確。這就是反射的意思:在運行時,確定對象的類型。
19.2 Class類
會引起父類的被加載
如何用父類的Class對象找到子類
package com.tutorialspoint;import java.lang.*;public class ClassDemo {public static void main(String[] args) {try {ClassDemo cls = new ClassDemo();ClassDemo subcls = new SubClass1(); // class ClassDemoClass c = cls.getClass(); System.out.println(c);// sub class SubClass1Class c1 = subcls.getClass();System.out.println(c1);// represent a subclass of the specified class objectClass retval = c1.asSubclass(c);System.out.println(retval);} catch(ClassCastException e) {System.out.println(e.toString());}} }class SubClass1 extends ClassDemo {// sub class }我自己感覺這種獲取方法很雞肋,因為你還是需要得到子類的Class對象,才能確定子類
這個的輸出結果是這個
class reflection.toys.FancyToy
可以說,Class對象轉化成字符串的默認格式就是上面這樣的
Class對象存在一個cast()方法,這個方法是用來轉型用的,就是將某一個類的實例對象轉化成Class對象指定的類
動態代理
我看的博客https://www.cnblogs.com/gonjan-blog/p/6685611.html
https://segmentfault.com/a/1190000040680716
這里面第二個參數表示的是Person這個接口的Class對象
動態代理的優勢在于可以很方便的對代理類的函數進行統一的處理,而不用修改每個代理類中的方法。是因為所有被代理執行的方法,都是通過在InvocationHandler中的invoke方法調用的,所以我們只要在invoke方法中統一處理,就可以對所有被代理的方法進行相同的操作了。
這里注意下指的是代理類的代理對象里每一個方法前都被加了這個,而如果用的靜態代理的話,我們只能對具體的方法進行操作,這里的一個關鍵轉變就是將具體的方法轉化成了invoke方法的調用
Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);然后注意下這一行,stuProxy是Person接口的一個實例,所以可以調用下面的givemoney方法.我提前想錯了以為是代理類的實例,然后因為他只有一個invoke方法讓我有點難以理解可以調用不同的方法
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Processes a method invocation on a proxy instance and returns the result. This method will be invoked on an invocation handler when a method is invoked on a proxy instance that it is associated with.
-
Parameters:
proxy - the proxy instance that the method was invoked on
method - the Method instance corresponding to the interface method invoked on the proxy instance. The declaring class of the Method object will be the interface that the method was declared in, which may be a superinterface of the proxy interface that the proxy class inherits the method through.
args - an array of objects containing the values of the arguments passed in the method invocation on the proxy instance, or null if interface method takes no arguments. Arguments of primitive types are wrapped in instances of the appropriate primitive wrapper class, such as java.lang.Integer or java.lang.Boolean.
這里invoke的第三個參數是方法參數,就是我們平常的.printf().
其他
總結
以上是生活随笔為你收集整理的2022.2.13java学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java学习笔记 2022.2.11
- 下一篇: on java 8学习笔记