java学习笔记2022.2.11

on java 8 摘录(反射)

  1. 面向对象编程的一个基本目标就是,让编写的代码只操纵基类(本例中为Shape)的引用

  2. Shape接口中的方法draw()是可以动态绑定的,因此客户程序员可以通过泛化的Shape引用来调用具体的draw()方法。在所有子类中,draw()都被重写,并且因为它是一个动态绑定的方法,即使通过泛化的Shape引用来调用它,也会产生正确的行为。这就是多态。

  3. abstract class Shape {
      void draw() {
        System.out.println(this + ".draw()");
      }
      @Override public abstract String toString();
    }
    
    class Circle extends Shape {
      @Override public String toString() {
        return "Circle";
      }
    }
    
    class Square extends Shape {
      @Override public String toString() {
        return "Square";
      }
    }
    
    class Triangle extends Shape {
      @Override public String toString() {
        return "Triangle";
      }
    }
    public class Shapes {
      public static void main(String[] args) {
        Stream.of(
          new Circle(), new Square(), new Triangle())
          .forEach(Shape::draw);
      }
    }
    
  4. 这就是反射的意思:在运行时,确定对象的类型。

当程序第一次引用该类的静态成员时,就会触发这个类的加载。构造器是类的一个静态方法,尽管没有明确使用static关键字。因此,使用new操作符创建类的新对象也算作对该类静态成员的引用,构造器的初次使用会导致该类的加载。

一旦该类型的Class对象加载到内存中,它就会用于创建该类型的所有对象。

// reflection/SweetShop.java
// 检查类加载器的工作方式

class Cookie {
static { System.out.println("Loading Cookie"); }
}

class Gum {
static { System.out.println("Loading Gum"); }
}

class Candy {
static { System.out.println("Loading Candy"); }
}

public class SweetShop {
public static void main(String[] args) {
 System.out.println("inside main");
 new Candy();
 System.out.println("After creating Candy");
 try {
   Class.forName("Gum");
 } catch(ClassNotFoundException e) {
   System.out.println("Couldn't find Gum");
 }
 System.out.println("After Class.forName(\"Gum\")");
 new Cookie();
 System.out.println("After creating Cookie");
}
}
/* 输出:
inside main
Loading Candy
After creating Candy
Loading Gum
After Class.forName("Gum")
Loading Cookie
After creating Cookie
*/

我相信最开始肯定也有人和我一样没看懂为什么这个可以证明,其实是这样的,我们通过观察,可以发现上面类的顺序是Cookie,Gum,Candy这样的顺序下来的,而在下面我最先创建的是Candy,然后Gum,最后Cookie,然后又因为静态方法是类第一次被加载时会出现,那么按照常理,如果它们是提前编译好的,而不是在动态加载的话,它们的输出应该是乱的,或者就是按照编写顺序下来的,我说乱是因为提前全部加载的话,静态代码块一定会一起出现,但是会根据编译器决定哪个加载的块,这样就会导致顺序出问题;综上,既然它是按照主程序的顺序下来,那么肯定就只能是动态加载了.

newInstance()在Java 8中还是正常的,但在更高版本中已被弃用,Java推荐使用Constructor.newInstance()来代替。示例中我们使用了@SuppressWarnings("deprecation")来抑制那些更高版本的弃用警告。

这个可以这么写

Class up = c.getSuperclass();
Object obj = null;
try {
    // 对应类要有public的无参构造器:
    obj = up.getConstructor().newInstance();
} catch(Exception e) {
    throw new RuntimeException("Cannot instantiate");
}

on java 8 摘录(反射)(没看懂的东西)

  1. 事实上,Class对象被用来创建类的所有“常规”对象。

这句话我没太看懂,什么叫做常规对象?

我们对forName()的调用只是为了它的副作用:如果类Gum尚未加载,则加载它。在加载过程中,会执行Gum的静态代码块。

19.2 Class对象

  1. Class对象有点像静态对象的感觉,它们只被加载一次,后面都是对它的引用

  2. 有关于Class.forName(),这个写的挺详细的https://www.geeksforgeeks.org/class-forname-method-in-java-with-examples/,然后类名.getclass(),两个调用的方式不一样.

  3. 我魔改了on java 程序

    package test;
    class Cookie {
        static { System.out.println("Loading Cookie"); }
    }
    
    class Gum {
        static { System.out.println("Loading Gum"); }
    }
    
    class Candy {
        static { System.out.println("Loading Candy"); }
    }
    
    public class SweetShop {
        public static void main(String[] args) {
            System.out.println("inside main");
            new Candy();
            try {
                Class.forName("Candy");
            }catch (ClassNotFoundException e){
                e.printStackTrace();
            }
            System.out.println("After creating Candy");
            try {
               Class.forName("test.Gum");
            }catch (ClassNotFoundException e){
                e.printStackTrace();
            }
            System.out.println("After Class.forName(\"Gum\")");
            new Cookie();
            System.out.println("After creating Cookie");
        }
    }
    

其他

  1. toString()方法存在是因为我们需要类的字符串信息,如果没有这个方法的话,你的实例对象传出去的是它的地址
  2. 类的静态成员只会被加载一次,静态代码块也是一样
  3. 在idea中注意下,找类的话不是用的绝对地址而是相对地址.针对我上面给出的那个代码
  4. 看了反射,最大的感觉就是它可以无视具体的类编程,主要框架适用就好
  • 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、付费专栏及课程。

余额充值