精华内容
下载资源
问答
  • 反射全解

    万次阅读 多人点赞 2019-10-31 17:06:00
    反射的概念 反射的引入: Object obj = new Student(); 若程序运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象运行类型的方法: 1.若编译和运行类型都知道,使用 instanceof...

    反射的概念

    反射的引入:

    Object obj = new Student();

    若程序运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象运行类型的方法:

    1.若编译和运行类型都知道,使用 instanceof判断后,强转。

    2.编译时根本无法预知该对象属于什么类,程序只能依靠运行时信息来发现对象的真实信息,这时就必须使用反射了。

    3.要是想得到对象真正的类型,就得使用反射。

    什么是反射机制?  

            简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

    反射机制的优点与缺点:  

            为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念  

           静态编译:在编译时确定类型,绑定对象,即通过。  

           动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。  

           一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发。

    它的缺点是对性能有影响。

    使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

     

    Class类和Class类实例

     

    Java程序中的各个Java类属于同一类事物,描述这类事物的Java类就是Class类。

    对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?

    人  Person

    Java类  Class

    对比提问: Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个实例对象又分别对应什么呢?

    对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等;

    一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的;

    用类来描述对象,类:描述数据的结构

    用元数据来描述Class,MetaData(元数据):描述数据结构的结构;

    反射就是得到元数据的行为;

     

     

    备注:一个类在虚拟机中只有一份字节码;

     

    获得Class对象

     

    如何得到各个字节码对应的实例对象?

    每个类被加载后,系统会为该类生成对应的Class对象,通过Class对象可以访问到JVM中的这个类,

    3种方式:

    1、调用某个类的class属性获取Class对象,如Date.class会返回Date类对应的Class对象(其实就是得到一个类的一份字节码文件);

    2、使用Class类的forName(String className)静态方法,className表示全限定名;如String的全限定名:java.lang.String;

    3、调用某个对象的getClass()方法。该方法属于Object类;

    Class<?> clz = new Date().getClass();

    public class ClassDemo1 {
    
       public static void main(String[] args) throws Exception {
    
          //获得Class对象的方法(三种)
    
          //一:调用属性
    
          Class<String> c = String.class;
    
          System.out.println(c);//打印结果:class java.lang.String          String.class就表示JVM中一份表示String类的字节码
    
          Class<String> c2 = String.class;
    
          System.out.println(c == c2);//true都是String类的字节码        一个类在虚拟机中只有一份字节码;
    
         
    
          //二:使用forName()方法
    
          //Class cla = Class.forName("String");//ERROR,
    
          Class<String> cla =  (Class<String>)Class.forName("java.lang.String");//必须用上全限定名,否则报错
    
          System.out.println(c == cla);//true
    
         
    
          //三:利用对象调用Object的getClass方法;
    
          Class c3 = new String().getClass();
    
          System.out.println(c == c3);//ture
    
       }
    
    }

     

    我的总结:获取Class对象最常用的是利用属性的方法!

    九个预定义Class对象

     

    基本的 Java 类型(boolean、byte、char、short、int、long、float 、double)和关键字void通过class属性也表示为 Class 对象;

    Class类中boolean isPrimitive() :判定指定的 Class 对象是否表示一个基本类型。

    包装类和Void类的静态TYPE字段;

    Integer.TYPE == int.class ;         

    Integer.class == int.class;      

     数组类型的Class实例对象:

    Class<String[]> clz = String[].class;

    数组的Class对象如何比较是否相等? 数组的维数和数组的类型;

    Class类中 boolean isArray() :判定此 Class 对象是否表示一个数组类型。

    public class PreClassDemo2 {
       public static void main(String[] args) {
          Class<?> in = int.class;
          System.out.println(in);//int
          Class<?> in2 = Integer.class;
          //包装类都有一个常量TYPE,用来表示其基本数据类型的字节码
          Class<?> in3 = Integer.TYPE;
          System.out.println(in2);//class java.lang.Integer
    
          System.out.println(in3);//int
    
          System.out.println(in3 == in);//true 包装类都有一个常量TYPE,用来表示其基本数据类型的字节码,所以这里会相等!
    
          System.out.println(in3 == in2);//false
    
          Class<String[]> s = String [].class;
    
          Class<int[]> i = int [].class;
    
          //System.out.println(i ==s);//编译根本就通过不了,一个是int,一个是String
    
       }
    
       //这两个自定义的方法是可以的,一个int,一个Integer//包装类与基本数据类型的字节码是不一样的
       public void show(int i){}
       public void show(Integer i){}
    
    }

    利用Class获取类的属性信息

    import java.lang.reflect.Modifier;
     

    class A {
    
    }
    
    interface B{
    
    }
    
    interface C{
    
    }
    public class BaseDemo3 extends A implements B,C{
       //内部类
       public class C{}
       public interface D{}
       public static void main(String[] args) {
          //类可以,接口也可以
          Class<BaseDemo3> c = BaseDemo3.class;
          System.out.println(c);//class junereflect624.BaseDemo3
          //得到包名
          System.out.println(c.getPackage());//package junereflect62;
          //得到全限定名
          System.out.println(c.getName());//junereflect624.BaseDemo3
          //得到类的简称
          System.out.println(c.getSimpleName());//BaseDemo3
          //得到父类
          /**
           * Class<? super T> getSuperclass() 此处super表示下限
                   返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
           */
          System.out.println(c.getSuperclass().getSimpleName());//A,先获取父类,再获取父类的简称
          //得到接口
       System.out.println(c.getInterfaces());//[Ljava.lang.Class;@1b60280
          Class[] arr = c.getInterfaces();
          for (Class cla : arr) {
             System.out.println(cla);//interface junereflect624.B   interface junereflect624.C
          }
          //获得public修饰的类
          /**
           * Class<?>[] getClasses()
                    返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。 (如果内部类前面没有加上public的话那么得不到!)
           */
          Class[] cl = c.getClasses();
          System.out.println(cl.length);//在内部类没有加上public修饰的时候长度为0,加上就是2(获取的是公共的)
          for (Class class1 : cl) {
             System.out.println(class1);
          }
          //获得修饰符
          int i = c.getModifiers();
          System.out.println(i);//常量值1表示public
          System.out.println(Modifier.toString(i));//直接打印出public
       }
    }

    Class中得到构造方法Constructor、方法Method、字段Field

    常用方法:

    Constructor类用于描述类中的构造方法:

    Constructor<T> getConstructor(Class<?>... parameterTypes)

    返回该Class对象表示类的指定的public构造方法;

    Constructor<?>[] getConstructors()

    返回该Class对象表示类的所有public构造方法;

    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

    返回该Class对象表示类的指定的构造方法,和访问权限无关;

    Constructor<?>[] getDeclaredConstructors()

    返回该Class对象表示类的所有构造方法,和访问权限无关;

     

    Method类用于描述类中的方法:

    Method getMethod(String name, Class<?> ... parameterTypes)

    返回该Class对象表示类和其父类的指定的public方法;

    Method[] getMethods(): 

    返回该Class对象表示类和其父类的所有public方法;

    Method getDeclaredMethod(String name, Class<?>... parameterTypes)

    返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

    Method[] getDeclaredMethods(): 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;

     

    Eg:

    import java.lang.reflect.Constructor;

    class Emp{
       private String name;
       private int age;
       private Emp() {
       }
       Emp(String name){
       }
       public Emp(String name,int age){
       }
    }

     

    public class ConstructorDemo4 {
       public static void main(String[] args) throws Exception {
          //得到所有的构造器(先得到类)
          Class<Emp> c = Emp.class;
          /**
           * Constructor<?>[] getConstructors()
                   返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
           */
          Constructor[] con = c.getConstructors();//前面的修饰符必须是public才可以在这个方法下获取到
          for (Constructor cons : con) {
             System.out.println("c.getConstructors()"+cons);//如果上面的某构造器public去掉,则显示不出
             /**打印
                public junereflect624.Emp(java.lang.String,int)
              */
          }
    
          //得到指定的构造器,也是必须public
          Constructor c1 = c.getConstructor(String.class,int.class);
          System.out.println(c1);//public junereflect624.Emp(java.lang.String,int)
    
    System.out.println("====================================");
    
       //现在想获得不受public影响的,getDeclaredConstructors(),暴力反射
         
          con = c.getDeclaredConstructors();
          for (Constructor cons : con) {
    System.out.println("c.getDeclaredConstructors()=="+cons);//此时不受修饰符的影响
             /**打印
              *  public junereflect624.Emp()
                public junereflect624.Emp(java.lang.String)
                public junereflect624.Emp(java.lang.String,int)
              */
          }
       }
    }
    
    

     

    import java.lang.annotation.Annotation;

    import java.lang.reflect.Field;

    import java.lang.reflect.Method;

    class AB{
    
       protected String name;
    
       protected String id;
    
    }
    @Deprecated
    
    public class MethodDemo5 extends AB{
       void show(){}
       public void say(){}
       private int age;
       public char c;
       private boolean b;
       public static void main(String[] args) throws Exception {
          Class<MethodDemo5> c = MethodDemo5.class;
          //获取所有的(包含父类的方法)public修饰的方法
          Method[] m = c.getMethods();
          for (Method method : m) {
             System.out.println(method);
          }
          //总结:4个方法,获取全部,获取特定;不受修饰符影响的全部,不受修饰符影响的特定;(前两个都还是受限制的)
          //获取指定的方法
          Method me = c.getMethod("main", String[].class);
          System.out.println("main "+me);//main public static void junereflect624.MethodDemo5.main(java.lang.String[]) throws java.lang.Exception
          //访问所有方法,不受访问权限影响
          m = c.getDeclaredMethods();
          for (Method method : m) {
             System.out.println("不受影响的:"+method);
          }
          me = c.getDeclaredMethod("show");
          System.out.println(me);//void junereflect624.MethodDemo.show()
          me = c.getMethod("toString");
          System.out.println(me);//public java.lang.String java.lang.Object.toString()
          /**
           * Method[] getDeclaredMethods()
                    返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法,只可以对当前类有效
           */
          /*me = c.getDeclaredMethod("toString");//ERROR,c.getDeclaredMethod()不能得到继承的方法
          System.out.println(me);//public java.lang.String java.lang.Object.toString()
           */
          //得到字段
          Field[] f = c.getFields();
          for (Field field : f) {//只得到了public的
             System.out.println("字段"+field);
          }
          //特定字段
          Field fi = c.getField("c");//""里面是名称
          System.out.println(fi);//public char junereflect624.MethodDemo.c
          //得到不受限定名限定的全部字段
          f = c.getDeclaredFields();
          for (Field field : f) {//得到不受修饰符限定的字段,但是只对当前类有效
             System.out.println("全部字段:"+field);
             /**
              * 全部字段:private int junereflect624.MethodDemo.age
              * 全部字段:public char junereflect624.MethodDemo.c
              * 全部字段:private boolean junereflect624.MethodDemo.b
              */
          }
          //注释  Annotation
           Annotation[] a = c.getAnnotations();
           System.out.println(a.length);
           for (Annotation annotation : a) {
             System.out.println(annotation);
          }
           //特定注解
           Deprecated d = c.getAnnotation(Deprecated.class);
           System.out.println(d);
       }
    }

    获取当前对象的字段:

    import java.lang.reflect.Field;
    class Stu{
       public String name;
       public String sex;
       public int age;
       public Stu(String name, String sex, int age) {
          super();
          this.name = name;
          this.sex = sex;
          this.age = age;
       }
    }
    
    public class ReflectDemo6 {
       public static void main(String[] args) throws Exception {
          Stu s = new Stu("刘昭", "男", 12);
          Class<Stu> c = Stu.class;
          Field f = c.getField("name");
          System.out.println(f.get(s));从哪个对象身上取!此时显示刘昭!
    // 修改对象的值
    /**
    Field f = c.getField("name");
          f.set(s,"章泽天");
    System.out.println(f.get(s));//从哪个对象身上取!//此时显示章泽天
    */
    
       }
    
    }

    我的总结:对于方法,字段,构造方法之类用类获取记住四个:获取全部,获取特定,暴力获取全部,暴力获取特定!

    利用反射创建对象

    创建对象:

    1、使用Class对象的newInstance()方法创建该Class对象的实例,此时该Class对象必须要有无参数的构造方法。

    2、使用Class对象获取指定的Constructor对象,再调用Constructor的newInstance()方法创建对象类的实例,此时可以选择使用某个构造方法。如果这个构造方法被私有化起来,那么必须先申请访问,将可以访问设置为true;

    Eg:

    最简单的:

    class User{
    //将默认的构造方法私有化的话就不可以再创建对象,两种方法都是这样
       /*private User(){}*/
       public String toString() {
          return "User对象创建成功!";
       }
    }
    public class NewInstanceDemo6 {
       public static void main(String[] args) throws Exception {
          //传统方式创建对象
           System.out.println(new User());
           //使用反射的方式
           Class<User> c = User.class;
           User u = c.newInstance();(直接newInstance的话必须保证默认的构造方法正常存在,也就是没有被私有化!这是前提条件)
           System.out.println(u);
       }
    }

    复杂点的:更强大的第二种:

    使用指定构造方法来创建对象:

    获取该类的Class对象。

    利用Class对象的getConstructor()方法来获取指定的构造方法。

    调用Constructor的newInstance()方法创建对象。

    AccessibleObject对象的setAccessible(boolean flag)方法,当flag为true的时候,就会忽略访问权限(可访问私有的成员)

    其子类有Field, Method, Constructor;

    若要访问对象private的成员?

    在调用之前使用setAccessible(true),

           Xxx x = getDeclaredXxxx();//才能得到私有的类字段.

    总结步骤:

    1. 获取该类的Class对象。
    2. 利用Class对象的getConstructor()方法来获取指定的构造方法。
    3. 申请访问(设置为可访问)
    4. 调用Constructor(构造方法)的newInstance()方法创建对象。

    例子

    import java.lang.reflect.Constructor;

    class Per{
       private String name;
       private int age;
       private Per(){  
       }
       private Per(String name){
       }
       public String toString() {
          return "对象!!!";
       }
    }
    public class NewInstanceDemo7 {
       public static void main(String[] args) throws Exception {
          Class<Per> c = Per.class;
          //System.out.println(c.newInstance());;//证明利用无参的可以
          先获得需要被调用的构造器(private 修饰的构造方法)
          Constructor<Per> con = c.getDeclaredConstructor();//调用默认的,什么都不要写
          System.out.println(con);//private junereflect624.Per()
          /*con = c.getDeclaredConstructor(String.class);获取指定的构造方法
          System.out.println(con);//private junereflect624.Per(java.lang.String)*/    
          //现在只需要执行这个构造器,
          /**
           *  T newInstance(Object... initargs)
                使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
           */
          //私有的成员是受保护的,不能直接访问
          //若要访问私有的成员,得先申请一下
          con.setAccessible(true);//允许访问
          Per p = con.newInstance();//成功,通过私有的受保护的构造方法创建了对象
          System.out.println("无参构造方法"+p);
          con = c.getDeclaredConstructor(String.class);
          System.out.println(con);//private junereflect624.Per(java.lang.String);              
          con.setAccessible(true);//允许访问
          p = con.newInstance("liuzhao");//成功,通过私有的受保护的构造方法创建了对象
          System.out.println("String构造方法"+p);
       }
    }

    备注:对于此时的话,单例模式就不再安全了!反射可破之!!

    使用反射调用方法

    每个Method的对象对应一个具体的底层方法。获得Method对象后,程序可以使用Method里面的invoke方法来执行该底层方法。

    Object invoke(Object obj,Object ... args):obj表示调用底层方法的对象,后面的args表示传递的实际参数。

    如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null,想想为什么?

    如果底层方法所需的形参个数为 0,则所提供的 args 数组长度可以为 0 或 null。

    不写,null,或 new Object[]{}

    若底层方法返回的是数组类型,invoke方法返回的不是底层方法的值,而是底层方法的返回类型;

    import java.lang.reflect.Method;

    class Dept{
       public String show(String name){//用反射的方法来调用正常的方法
          return name+",您好!";
       }
       private void privateshow(){//用反射来实现对私有化方法的调用
          System.out.println("privateshow");
       }
       public static void staticshow(){
          System.out.println("staticshow");
       }
    }
    public class InvokeDemo9 {
       public static void main(String[] args) throws Exception {  
    /* 传统方式:
    String name = new Dept().show("刘昭");
          System.out.println(name);*/    
    
    /**
           * Method getMethod(String name, Class<?>... parameterTypes)
                   返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指         定公共成员方法。
              name - 方法名
             parameterTypes - 参数列表
           */
          //想要通过反射来调用Dept中的方法
          Class<Dept> c = Dept.class;
          Method m = c.getMethod("show", String.class);
          Object o = m.invoke(c.newInstance(), "刘昭");
          System.out.println(o);
        
          //私有化的方法
          m = c.getDeclaredMethod("privateshow");//无参方法
          m.setAccessible(true);
          o = m.invoke(c.newInstance());
         
          //静态方法的调用
          m = c.getMethod("staticshow");
          m.invoke(null);//staticshow为静态方法,不需创建对象,所以这里会是null
       }
    }

    打印

    刘昭,您好!

    privateshow

    staticshow

    使用反射操作字段

    Field提供两组方法操作字段:

    xxx getXxx(Object obj):获取obj对象该Field的字段值,此处的xxx表示8个基本数据类型。若该字段的类型是引用数据类型则使用,Object get(Object obj);

    void setXxx(Object obj,xxx val):将obj对象的该Field字段设置成val值,此处的xxx表示8个基本数据类型。若该字段的类型是引用数据类型则使用,void set(Object obj, Object value);

    package junereflect624;

    //获取字符,并且赋值,然后再取出来(对应的去查看api,比如这个是Field,别的比如Constructor,Method)

    步骤:

    1. 获取类
    2. 获取字段
    3. 赋值(set(c.newInstance(),””));{如果为私有的话设置可接受}

    import java.lang.reflect.Field;

    class Cat{
       private String name;
       public int age;
       private String color;
    }
    public class FieldDemo12 {
       public static void main(String[] args) throws Exception {
          Class<Cat> clz = Cat.class;
          Field[] f = clz.getDeclaredFields();
         
          for (Field field : f) {
             System.out.println(field);
          }
        
          Field fi = clz.getDeclaredField("name");
          System.out.println(fi);
        
          System.out.println(fi.getName());//name
         
          //核心开始
          /**
          *  void set(Object obj, Object value)
    将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
           */
          Cat c = clz.newInstance();
          fi.setAccessible(true);
          fi.set(c, "刘昭");//赋值成功
          Object o = fi.get(c);
          System.out.println(o);//取出成功
         
          fi = clz.getDeclaredField("age");
          fi.setAccessible(true);
          fi.set(c, 21);
          int i = fi.getInt(c);//左边的接受类型已经写成了int,右边的返回类型就也必须是int
          System.out.println(i);//获取成功
       }
    }

     

    打印

    private java.lang.String junereflect624.Cat.name

    public int junereflect624.Cat.age

    private java.lang.String junereflect624.Cat.color

    private java.lang.String junereflect624.Cat.name

    name

    刘昭

    21

     

    反射和泛型-反射来获取泛型信息

    通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public。获得Field对象后都可以使用getType()来获取其类型。

    Class<?> type = f.getType();//获得字段的类型

    但此方法只对普通Field有效,若该Field有泛型修饰,则不能准确得到该Field的泛型参数,如Map<String,Integer>;

    为了获得指定Field的泛型类型,我们采用:

    Type gType = f.getGenericType();得到泛型类型

    然后将Type对象强转为ParameterizedType,其表示增加泛型后的类型

    Type getRawType()//返回被泛型限制的类型;

    Type[]  getActualTypeArguments()//返回泛型参数类型;

     

    利用反射来获取泛型的类型(泛型信息)

    步骤:

    1. 获取当前类
    2. 获取目标字段
    3. 获取包含泛型类型的类型 getGenericType()
    4. 强转至子类ParameterizedType   因为Type没有任何对应的方法
    5. 获得泛型真正的类型 getActualTypeArguments()
    import java.lang.reflect.Field;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.HashMap;
    import java.util.Map;
    public class GetGenericTypeDemo14 {
       Map<String,Integer> map = new HashMap<String,Integer>();
      
       public static void main(String[] args) throws Exception {
          Class c = GetGenericTypeDemo14.class;
          Field f = c.getDeclaredField("map");
          System.out.println(f);
          System.out.println(f.getName());//map
         
          // Class<?> getType()  返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
          Class cl = f.getType();
          System.out.println("获得其类型:"+cl);
    //获得其类型:interface java.util.Map
        
          /**
           *  Type getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。
           *  Type是Class的接口;
           */
          Type t = f.getGenericType();//包含泛型的类型
          System.out.println(t);
    //java.util.Map<java.lang.String, java.lang.Integer>
         
          /**
           * Type这个类里面没有任何的方法,所以需要调用子类的方法,那么大的类型转到小的类型,需要强转!
           */
          ParameterizedType pt = (ParameterizedType)t;//强转到其子类
          /**
           *  Type[] getActualTypeArguments()
                       返回表示此类型实际类型参数的 Type对象的数组。
              Type getOwnerType()
                       返回 Type 对象,表示此类型是其成员之一的类型。
              Type getRawType()
                       返回 Type 对象,表示声明此类型的类或接口。
           */
         
          t = pt.getRawType();//类型的类或接口
          System.out.println(t);
         
          Type[] ts = pt.getActualTypeArguments();
          for (Type type : ts) {
             System.out.println(type);
             /**
              *  class java.lang.String
                 class java.lang.Integer
              */
          }
       }
    }

    打印:

    java.util.Map junereflect624.GetGenericTypeDemo14.map

    map

    获得其类型:interface java.util.Map

    java.util.Map<java.lang.String, java.lang.Integer>

    interface java.util.Map

    class java.lang.String

    class java.lang.Integer

    我的总结:多查找api,参考api中方法使用的限制,比如是否静态、返回值类型等。

    展开全文
  • 主要介绍了Python中的反射描述器一些知识的汇总,非常的详细,有需要的小伙伴可以参考下
  • 该模型在传统构件模型的基础上,引入本体及反射技术,使得构件语义描述丰富,并能根据系统要求及运行环境的变化,构件进行动态修改。同时,该模型支持自动组装和推理。通过移动应用场景该模型进行验证,结果表明,该...
  • Java 反射和映射(主要描述反射)

    万次阅读 2017-12-04 17:42:17
    什么是反射?等同于映射吗? 完全不相关的。反射是一个机机制,映射是一种关系。 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和...

    什么是反射?等同于映射吗?

        完全不相关的。反射是一个机机制,映射是一种关系。

           反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

        映射是一种对应关系,在很多的情况下,表示一种存在的联系而已。

     

    反射能做什么

     

    • 在运行时判断任意一个对象所属的类;

    • 在运行时构造任意一个类的对象;

    • 在运行时判断任意一个类所具有的成员变量和方法;

    • 在运行时调用任意一个对象的方法;

    • 生成动态代理。

     
     
         通俗的讲,当某些API没有暴露出来,但是我们又需要用到其中的某些方法属性就需要了。
     
     
    ForExample:
     
    //假如JavaBean没有暴露出构造方法package mypackage;

     
    public class JavaBean {
    
    
    private int age;
    private String name;
    public  String adress;
    public int getAge() {
    return age;
    }
    private void setAge(int age) {
    this.age = age;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getAdress() {
    return adress;
    }
    public void setAdress(String adress) {
    this.adress = adress;
    }
    
            
    }
     
    
    //我们可以通过Class类来获取实例对象
    
    package mypackage;
    
    
    import java.lang.reflect.Method;
    
    
    public class JNITest {
      public static native void  getStringFromC();
    public static void main(String[] args) {
    
    
           try {
               //获取类
               Class<?> class1 = Class.forName("mypackage.JavaBean");
    
    
               //获取所有的公共的方法
               Method[] methods =  class1.getMethods() ;
               
               for (Method method : methods) {
                   System.out.println( method );
               }
               //获取实例类
               Object object  = class1.newInstance();
               JavaBean javaBean  = (JavaBean)object;
               javaBean.setName("Hellow");
               System.out.println("--->"+javaBean.getName());
    
    
              } catch (Exception e) {
               e.printStackTrace();
           }
       }
    
    
    }
     
    运行结果:
    public java.lang.String mypackage.JavaBean.getName()
    public void mypackage.JavaBean.setName(java.lang.String)
    public java.lang.String mypackage.JavaBean.getAdress()
    public void mypackage.JavaBean.TestMethod()
    public int mypackage.JavaBean.getAge()
    public void mypackage.JavaBean.setAdress(java.lang.String)
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    --->Hellow
     
     

     

     

     

    展开全文
  • 反射机制反射机制反射机制反射机制反射机制反射机制反射机制反射机制反射机制反射机制反射机制
  • 为研究该响应,提出调制偏振的复信号描述方法,在测量系统的全局坐标系下,结合偏振传递参数获得反射调制偏振的复信号表示。分析了正入射时未镀膜实心(BK7)和空心(Au膜层)角反射调制偏振的偏振响应特性;...
  • 光电反射传感器 红外对管模块

    万次阅读 多人点赞 2018-12-07 16:49:28
    模块描述 可通过电位器旋钮调节检测距离,有效距离范围 2~30mm,检测角度35度,工作电压为 3.3V-5V。 该传感器的探测距离可以通过电位...黑色灯管为接收管,接受反射回来的红外 两个指示灯:电源指示灯、输出...

     

    模块描述

    可通过电位器旋钮调节检测距离,有效距离范围 2~30mm,检测角度35度,工作电压为 3.3V-5V。

    该传感器的探测距离可以通过电位器调节、具有干扰小、便于装配、使用方便等特点,

    可以广泛应用于机器人避障、避障小车、流水线计数及黑白线循迹等众多场合。

    部件

    两个灯管:白色灯管为发射管,发射红外光;黑色灯管为接收管,接受反射回来的红外光

    两个指示灯:电源指示灯、输出指示灯

    模块接口说明

    • VCC 外接 3.3V-5V 电压(建议3.3V
    • GND 外接 GND
    • OUT 接开发板或单片机的GPIO口(输出0 或 1)

    使用时

    • 发射管(白色灯管)发射出一定频率的红外线,当检测方向遇到障碍物(反射面)时,红外线反射回来被接收管(黑色灯管)接受,经过比较器电路处理后,输出指示灯会亮起,同时输出数字信号(低电平信号)。

    两个指示灯,三种状态

    通电时,电源指示灯常亮,

    • 距离较远、未感应到障碍物时,输出指示灯灭,OUT引脚输出高电平
    • 距离近,感应到障碍物时,输出指示灯亮,OUT端口输出低电平
    • 距离近,遇到黑色障碍物时,黑色灯管接收不到,输出指示灯灭,OUT引脚输出高电平

    检测距离调节

    检测距离2~30mm,可以通过电位器进行调节,顺时针调节电位器,检测距离增加;逆时针调节电位器,检测距离减少。

    STM32驱动代码参考

    #include "infrared.h"
    
    void INFRARED_Init(void)
    {
    	RCC->APB2ENR|=1<<3;           // 使能GPIOB时钟
    
    	GPIOB->CRH &= 0XFFF00FFF;     //PB11、PB12 浮空输入
    	GPIOB->CRH |= 0X00004400;
    }

    寻迹/循迹

    循迹是指自制的小车能够沿黑线(黑色电胶布)构成的直线或曲线行驶(行驶在指定区域内)。

    安装好红外对管的小车正常放在地板上(无黑线)时,输出指示灯应

    • 一只红外对管

    将红外对管安装在小车右前方(左前方),使小车可以沿着右(左)侧黑线行驶。

    思路:让小车一直右转,碰到黑线时左转。

    //沿右侧黑线循迹伪代码
    while(1)
    {
        if(输出指示灯灭)  //碰到黑线
            小车左转;
        小车右转;
    }
    //沿左侧黑线循迹同理
    • 两只红外对管
      • 一条黑线

    两个红外对管均放置在小车前方,两个黑管的间距理论上应略大于黑线宽度的根号2倍(直角)。(跨于黑线两侧)

    while(1)
    {
        if(左对管输出指示灯灭 && 右对管输出指示灯亮)    //左对管碰到黑线
            小车左转;
        if(左对管输出指示灯亮 && 右对管输出指示灯灭)
            小车右转;
    }

     

    展开全文
  • 描述了内腔He-Ne激光器的偏振性质对反射光束强度的影响,指出通常使用的45°射角的参考光束不能消除测量光束强度变化的影响,而当入射角小于15°时,才能得到满意的结果。
  • 反射

    千次阅读 多人点赞 2019-07-14 20:30:55
    反射1.什么是反射反射的优点反射的缺点2. 类类3.一切反射相关的代码都从获得java.lang.Class类对象开始4. 反射三大作用(java.lang.reflect.*)4.1获取类对象的三种方式4.2反射实例化对象4.3 反射动态调用方法4.4 反射...

    1.什么是反射

    反射是java语言中的一种机制,通过机制可以动态的实例化对象,读写属性、调用方法

    反射的优点

    反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创和控制任何类的对象,无需提前硬编码目标类

    反射的缺点

    性能问题,使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用

    2. 类类

    所有狗 狗类 Dog 狗对象 旺财
    所有猫 猫类 Cat 猫对象 肥波
    所有类 类类 java.lang.Class 类对象 特定类

    java.lang.Class
    java.lang.reflect.Method
    java.lang.reflect.Field
    java.lang.reflect.construct
    

    (Dog.java , Cat.java…).java文件我们能不能描述成一种事物呢?
    java.lang.Class这个类就是描述Dog.java,Cat,java这些东西的
    具体的.java文件就是描述java.lang.Class这个类的一个具体的实例

    类组成部分:
    类属性 java.lang.reflect.Field (都是以java面向对象的思想对它进行封装了)
    类方法 java.lang.reflect.Method

    3.一切反射相关的代码都从获得java.lang.Class类对象开始

    3.1 Class.forName(完整类名)
    3.2 类名.class
    3.3 对象.getClass()

    4. 反射三大作用(java.lang.reflect.*)

    4.1获取类对象的三种方式

    代码演示:
    创建一个Student

    package com.myy.reflect;
    
    public class Student {
    	private String sid;
    
    	private String sname;
    
    	public Integer age;
    	
    	static{
    		System.out.println("加载进jvm中!");
    	}
    
    	public Student() {
    		super();
    		System.out.println("调用无参构造方法创建了一个学生对象");
    	}
    
    	public Student(String sid) {
    		super();
    		this.sid = sid;
    		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
    	}
    
    	public Student(String sid, String sname) {
    		super();
    		this.sid = sid;
    		this.sname = sname;
    		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
    	}
    
    	@SuppressWarnings("unused")
    	private Student(Integer age) {
    		System.out.println("调用Student类私有的构造方法创建一个学生对象");
    		this.age = age;
    	}
    
    	public String getSid() {
    		return sid;
    	}
    
    	public void setSid(String sid) {
    		this.sid = sid;
    	}
    
    	public String getSname() {
    		return sname;
    	}
    
    	public void setSname(String sname) {
    		this.sname = sname;
    	}
    
    	public void hello() {
    		System.out.println("你好!我是" + this.sname);
    	}
    
    	public void hello(String name) {
    		System.out.println(name + "你好!我是" + this.sname);
    	}
    
    	@SuppressWarnings("unused")
    	private Integer add(Integer a, Integer b) {
    		return new Integer(a.intValue() + b.intValue());
    	}
    }
    
    

    Demo1:

    package com.myy.reflect;
    
    /**
     * 获取类对象的方式
     *  通过java提供的反射机制获取到com.myy.reflect.Student.class
     *  1.Class.forName("全路径名");   jdbc/自定义mvc框架调用
     *  2.类名.class 结合泛型做通用分页查询方法会用
     *  3.类java.lang.Class(实例的类)实例(Student.class)的类实例getClass()获取  通用的增删改结合泛型使用
     *  
     * @author myy
     *
     */
    public class Demo1 {
      public static void main(String[] args) throws Exception {
    //	 1.Class.forName("全路径名");   jdbc/自定义mvc框架调用
    	Class stuClz = Class.forName("com.myy.reflect.Student");
    	System.out.println("------------");
    	
    //	 2.类名.class 结合泛型做通用分页查询方法会用
    	Class stuClz1 = Student.class;
    	System.out.println(stuClz1);
    	System.out.println("-------------");
    	
    	Student stu = new Student();
    //	3.类java.lang.Class(实例的类)实例(Student.class)的类实例getClass()获取  通用的增删改结合泛型使用
    	Class stuClz2 =  stu.getClass();
    	System.out.println(stuClz2);//并且还调用了无参构造器
    	
    	
    }
    	
    }
    

    运行结果:
    在这里插入图片描述

    4.2反射实例化对象

    代码演示:
    Demo2:

    package com.myy.reflect;
    
    /**
     * 利用反射进行对象的实例化
     *    之前:通过new关键字进行实例化
     *    现在:通过java.lang.reflect.construct来实例化对象
     *    
     * @author myy
     *
     */
    public class Demo2 {
        public static void main(String[] args) throws Exception, Exception {
    		Student stu = new Student();
    		Class stuClz = stu.getClass();
    //		newInstance这个方法默认是使用无参构造器去实例化对象
    		Student stu2 = (Student) stuClz.newInstance();
    		System.out.println(stu2);//如果不是空就意味着创建出来
    	}
    }
    

    运行结果:
    在这里插入图片描述
    提问:假设没有无参构造器运行会不会报错
    代码演示:
    首先,先把Student类的无参构造器注释掉
    在这里插入图片描述
    然后,修改一下Demo2的代码

     public static void main(String[] args) throws Exception, Exception {
    //		Student stu = new Student();
    //		Class stuClz = stu.getClass();
        	Class stuClz = Student.class;
    //		newInstance这个方法默认是使用无参构造器去实例化对象
    		Student stu2 = (Student) stuClz.newInstance();
    		System.out.println(stu2);//如果不是空就意味着创建出来
    	}
    

    如图所示运行会报错:
    在这里插入图片描述

    答:由上面代码演示我们得知当没有无参构造器的时候运行会报错。
    运行报错的原因是:没有找到匹配方法,因为它默认找的是默认无参构造器。
    注意:一定要提供无参构造器

    优势:

    1. 能够对未知的对象进行实例化
    2. 能够对私有的构造器实例化对象

    1.1代码演示:

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //		调用有参构造器去实例化对象
        	Constructor<Student> constructor = stuClz.getConstructor(String.class);
        	Student stu2 = (Student)constructor.newInstance("张三");
        	
    	}
    

    运行结果:
    在这里插入图片描述
    1.2代码演示

    public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //		调用有参构造器去实例化对象(两个参数的)
        	Constructor<Student> constructor = stuClz.getConstructor(String.class,String.class);
        	Student stu2 = (Student)constructor.newInstance("t003","张三");
        	
    	}
    

    运行结果:
    在这里插入图片描述
    2.1如果按照以上的操作进行代码演示

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //    	调用私有构造器去实例化对象
        	Constructor<Student> constructor = stuClz.getConstructor(Integer.class);
        	Student stu2 = (Student)constructor.newInstance(18);
        	
    	}
    
    

    运行结果:
    在这里插入图片描述
    getConstructor与getDeclaredConstructoe的区别
    getConstructor只能获取被public修饰的构造器
    getDeclaredConstructoe被所有关键字修饰的构造器

    所以私有的要用getDeclaredConstructoe

    如代码演示:

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //    	调用私有构造器去实例化对象
        	Constructor<Student> constructor = stuClz. stuClz.getDeclaredConstructor(Integer.class);
        	Student stu2 = (Student)constructor.newInstance(18);
        	
    	}
    

    运行结果:
    在这里插入图片描述

    Class com.myy.reflect.Demo2 can not access a member of class com.myy.reflect.Student with modifiers "private"
    

    该错误原因是:找到了私有的构造器,但不能调用因为没有权限

    则要对代码进行给予权限如代码演示:

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //    	调用私有构造器去实例化对象
        	Constructor<Student> constructor = stuClz. stuClz.getDeclaredConstructor(Integer.class);
    constructor.setAccessible(true);//默认为false    
    	Student stu2 = (Student)constructor.newInstance(18);
        	
    	}
    

    运行结果:
    在这里插入图片描述

    4.3 反射动态调用方法

    Demo3:
    无参的代码演示:

    package com.myy.reflect;
    
    import java.lang.reflect.Method;
    
    /**
     * 动态方法调用
     *  构造方法是不是方法
     * 
     * @author myy
     *
     */
    public class Demo3 {
     public static void main(String[] args) throws Exception, SecurityException {
    	Student stu = new Student();
    	Class<? extends Student> stuClz = stu.getClass();//泛型里的上限定
    //无参
    	Method m= stuClz.getDeclaredMethod("hello");
    	m.invoke(stu);
    }
    }
    

    运行结果:
    在这里插入图片描述
    有参的代码演示:

    public static void main(String[] args) throws Exception, SecurityException {
    	Student stu = new Student();
    	Class<? extends Student> stuClz = stu.getClass();//泛型里的上限定
    	//有参的
    	Method m= stuClz.getDeclaredMethod("hello", String.class);
    	m.invoke(stu, "张三");
    }
    
    

    运行结果:
    在这里插入图片描述
    私有的代码演示:

     public static void main(String[] args) throws Exception, SecurityException {
    	Student stu = new Student();
    	Class<? extends Student> stuClz = stu.getClass();//泛型里的上限定
    	//私有的
    	Method m = stuClz.getDeclaredMethod("add", Integer.class,Integer.class);
       m.setAccessible(true);
    	//	Method.invoke的返回值是被动态调用的方法的返回值
    	Object invoke = m.invoke(stu, 11,9);
    	System.out.println(invoke);
    }
    

    运行结果:
    在这里插入图片描述

    4.4 反射读写属性

    Demo4:
    代码演示:

    package com.myy.reflect;
    
    import java.lang.reflect.Field;
    
    /**
     * 反射读写属性
     *  自定义标签库,通用分页,自定义mvc也要用
     * @author myy
     *
     */
    public class Demo4 {
    public static void main(String[] args) throws Exception {
    	Student stu = new Student("t003","张三");
    	stu.age = 18;
    	System.out.println(stu.getSid());
        System.out.println(stu.getSname());	
    	Class<? extends Student> stuClz = stu.getClass();
    	//私有的
    	Field f = stuClz.getDeclaredField("sname");
    	f.setAccessible(true);
    	System.out.println(f.get(stu));
    	
    //	获取当前Student实例中的stu私有属性及其属性值
    	Field[] fields = stuClz.getDeclaredFields();
    	for (Field field : fields) {
    		field.setAccessible(true);
    		System.out.println(field.getName()+":"+field.get(stu));
    	}
    }
    }
    

    运行结果:
    在这里插入图片描述

    5.访问修饰符

    如何判断类或变量、方法的修饰符,可以使用Java反射机制中,Field的 getModifiers() 方法返回int类型值表示该字段的修饰符,

    即这个方法就是返回一个int型的返回值,代表类、成员变量、方法的修饰符。

    该修饰符是java.lang.reflect.Modifier的静态属性

    对应表如下:
    PUBLIC: 1
    PRIVATE: 2
    PROTECTED: 4
    STATIC: 8
    FINAL: 16
    SYNCHRONIZED: 32
    VOLATILE: 64
    TRANSIENT: 128
    NATIVE: 256
    INTERFACE: 512
    ABSTRACT: 1024
    STRICT: 2048
    

    Modifier提供了很多静态方法,对类和成员访问修饰符进行解码。
    如代码演示:

    package com.myy.reflect;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    
    /**
     *   Modifier.isAbstract(int mod) 
     *   Modifier.isFinal(int mod) 
     *   Modifier.isInterface(int mod)
     *   Modifier.isNative(int mod)
     *   Modifier.isPrivate(int mod)
     *   Modifier.isProtected(int mod) 
     *   Modifier.isStatic(int mod)
     *   Modifier.isStrict(int mod)
     *   Modifier.isSynchronized(int mod)  
     *   Modifier.isTransient(int mod)
     *   Modifier.isVolatile(int mod) 
     *   
     * @author myy
     *
     */
    public class Demo5 {
    public static void main(String[] args) {
         Field[] fileds = Student.class.getDeclaredFields();
         for (Field field : fileds) {
    		System.out.println(field.getName()+"  访问修饰符是否包括private:"+Modifier.isPrivate(field.getModifiers()));
    	    System.out.println(field.getName()+"  访问修饰符是否包括static:"+Modifier.isStatic(field.getModifiers()));
    	    System.out.println(field.getName()+"  访问修饰符是否包括public:"+Modifier.isPublic(field.getModifiers()));
         }
    }
    }
    

    运行结果:
    在这里插入图片描述

    展开全文
  • 该模型从数学上描述了旋转中心偏移和反射光强度调制之间的关系,定量地得出了光纤束结构参数传感器灵敏度和线性范围的影响。建立了高精度旋转中心偏移测量实验系统,模型进行了实验验证。在旋转中心偏移较小的...
  • 并且采用了一个指数矩阵来描述墨层产生的荧光光强, 从而得出了荧光半色调图像色彩的光反射规律。考虑到入射中从一种颜色油墨入射后再由同色油墨出射的概率要比从其它色油墨出射的概率要大的事实, 讨论中引入权重...
  • (多选)Java是一门支持反射的语言,基于反射为Java提供了丰富的动态性支持,下面关于Java反射描述,哪些是错误的:() A. Java反射主要涉及的类如Class, Method, Filed,等,他们都在java.lang.reflet包下 B. 通过...
  • 经过实验研究发现, 半椭圆模型形式的角度因子能更好地描述目标漫反射强度值随入射角的变化规律, 激光雷达强度值与接收功率间为线性转换规律; 在盲区范围外, 目标漫反射强度值随距离的变化遵循负指数规律。在实际应用...
  • 反射得到类的完整描述

    千次阅读 2012-06-08 17:31:12
    describeType函数在adobe官方在线文档上的定义如下:生成描述ActionScript对象(命令为方法的参数)的XML对象,此方法实现ActionScript语言的反射编程概念。 这个方法的应用场景可能是这样的:
  • 基于改进均值标准差曲线描述子的反射对称轴检测
  • 关于环境、漫反射、镜面反射

    千次阅读 2018-06-01 16:21:22
    1):环境:环境是一种低强度的,由光线经过周围环境表面多次反射后形成的,利用环境可以描述一块区域的亮度,通常在场 景中,环境的颜色是一个常量. 2):太阳:即定向光源,特点是从无穷远出发射光线,光线是...
  • 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1、使用new关键字:这是我们最常见的也是最简单的创建对象的方式 2、使用Clone的方法:无论何时...
  • 协议缓冲区和gRPC反射 此为(简称“ protobufs”)和提供了反射API。 protobufs中反射的核心是。 描述符本身就是protobuf消息,它描述.proto源文件或其中的任何元素。 因此,描述符的集合可以描述protobuf类型的...
  • C#反射机制来获取类 属性的描述

    千次阅读 2016-12-02 18:52:46
    通过C#反射获取类和类中属性的描述信息 自定义特性代码 [System.Serializable] [System.AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)] ...
  • Java基础篇:反射机制详解

    万次阅读 多人点赞 2018-09-29 10:19:50
    一、什么是反射反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行的时候才动态加载类,并且对于任意一个类,都能够知道这个类的所有属性和方法,调用方法/访问属性,不需要提前在编译期...
  • JAVA中的反射机制

    万次阅读 多人点赞 2014-01-08 22:31:58
    反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉它没有一个较深入的了解,这次重新学习了一下,感觉还行吧!  一,先看一下反射的概念:   主要是指程序可以访问,检测和...
  • 谈谈你对反射的理解

    千次阅读 2019-10-01 11:22:03
    而框架的灵魂就是反射),但是在实际的面试中,面试官经常会将它作为面试开头题目来检验你基础知识的掌握程度,以及逻辑表述能力等等,所以反射还是有必要了解了解。 下面我为大家总结一下反射的几个特点以及反射...
  • DirectX 9.0 (4)环境反射光

    千次阅读 2014-05-25 21:40:35
     这个公式的后半部分就是我们上一节中讲述的平行反射模型公式,而前面的那个公式就是环境的模拟公式,环境进行模拟,只要简单的指定环境的颜色以及物体环境的材质属性就可以了。简单吧!!! ...
  • 该项目包含很多工具类,本文只描述这两个简单的工具类,希望为你的工程有所帮助! 该源码中还有很多的有用的小工具,eg:json,xml,cache,sftp,ftp,io,proxy等,接下来小编会一个一个分享给大家,在年前的最后几天里,小编也...
  • Diffuse Lighting(漫反射光

    千次阅读 2016-07-07 18:27:45
    Diffuse Lighting(漫反射光) 不同的材质表面反射光的方式也不同。...漫反射表面对光反射在各个方向上都一样。 近似计算一个漫反射光,最简单并且最常用的模型是Lambert’s cosine law(朗伯余弦定律)。根据Lambe

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 145,422
精华内容 58,168
关键字:

对光反射描述