2022.2.13java学习笔记

2022.2.12

其他

  1. Object[] args表示的是命令行参数

2022.2.13

on java 8 (摘录)

  1. Class对象使用泛型语法时,newInstance()会返回对象的确切类型,而不仅仅是简单的Object,就像在ToyTest.java示例中看到的那样。但它也会受到一些限制:

    // reflection/toys/GenericToyTest.java
    // 测试Class类
    // {java reflection.toys.GenericToyTest}
    package reflection.toys;
    
    public class GenericToyTest {
      public static void
      main(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();
        // 只能生成Object
        Object obj = up.getConstructor().newInstance();
      }
    }
    

    如果你得到了基类,那么编译器只允许你声明这个基类引用是“FancyToy的某个基类”,就像表达式Class<? super FancyToy>所声明的那样。它不能被声明为Class<Toy>。这看起来有点儿奇怪,因为getSuperclass()返回了基类(不是接口),而编译器在编译时就知道这个基类是什么——在这里就是Toy.class,而不仅仅是“FancyToy的某个基类”。不管怎么样,因为存在这种模糊性,所以up.getConstructor().newInstance()的返回值不是一个确切的类型,而只是一个Object

    这里我是真感觉有意思,因为编译阶段确实应该知道基类的确切类型,而java本身又具有单继承机制,又不像c++的多继承会导致编译器不知道应该选择哪个基类,令人懵逼,让我感觉这个机制是不是从c++那里抄过来的,但又没有将它给融入进java的体系里,让人感觉另类

  2. Java中还有第三种形式的反射。这就是关键字instanceof,它返回一个boolean值,表明一个对象是否是特定类型的实例。

  3. 传统的类型转换。比如“(Shape)”,它使用反射来确保转型是正确的。如果你执行了错误的转型,它会抛出一个ClassCastException

  4. 代表对象类型的Class对象。你可以查询Class对象来获取有用的运行时信息。

问题

  1. 为什么在java在传统的类型转化中用到了反射.

    简单反射,它假定你在编译时就已经知道了所有可用的类型

    这是反射最基本的形式,在运行时检查了所有的类型转换是否正确。这就是反射的意思:在运行时,确定对象的类型。

19.2 Class

  1. Class<? super FancyToy> up = ftc.getSuperclass();
    

    会引起父类的被加载

  2. 如何用父类的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 ClassDemo
             Class c = cls.getClass(); 
             System.out.println(c);
    
             // sub class SubClass1
             Class c1 = subcls.getClass();
             System.out.println(c1);
    
             // represent a subclass of the specified class object
             Class retval = c1.asSubclass(c);
    
             System.out.println(retval);
          } catch(ClassCastException e) {
             System.out.println(e.toString());
          }
       }
    }
    
    class SubClass1 extends ClassDemo {
       // sub class
    } 
    

    我自己感觉这种获取方法很鸡肋,因为你还是需要得到子类的Class对象,才能确定子类

  3. Class<FancyToy> ftc = FancyToy.class;
            System.out.println(ftc);
    

    这个的输出结果是这个

    class reflection.toys.FancyToy

    可以说,Class对象转化成字符串的默认格式就是上面这样的

  4. Class对象存在一个cast()方法,这个方法是用来转型用的,就是将某一个类的实例对象转化成Class对象指定的类

动态代理

  1. 我看的博客https://www.cnblogs.com/gonjan-blog/p/6685611.html

    https://segmentfault.com/a/1190000040680716

  2. public static Object newProxyInstance(ClassLoader loader,
     Class<?>[] interfaces,
     InvocationHandler h)
    
  3. Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler)
    

    这里面第二个参数表示的是Person这个接口的Class对象

  4. 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。是因为所有被代理执行的方法,都是通过在InvocationHandler中的invoke方法调用的,所以我们只要在invoke方法中统一处理,就可以对所有被代理的方法进行相同的操作了。

    这里注意下指的是代理类的代理对象里每一个方法前都被加了这个,而如果用的静态代理的话,我们只能对具体的方法进行操作,这里的一个关键转变就是将具体的方法转化成了invoke方法的调用

    Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler)

    然后注意下这一行,stuProxy是Person接口的一个实例,所以可以调用下面的givemoney方法.我提前想错了以为是代理类的实例,然后因为他只有一个invoke方法让我有点难以理解可以调用不同的方法

  5. 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().

其他

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cjz-lxg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值