Java反射机制及其使用

Java反射机制及其使用文章目录1Java反射机制概述2反射及其使用2.1关于类java.lang.Class2.2类的加载2.2.1类的加载过程2.2.2类加载器2.3反射的使用2.3.1创建运行时类的对象2.3.2获取运行时类的属性结构2.3.3获取运行时类的方法结构2.3.4获取运行时类的构造器结构2.3.5获取运行时类的父类信息2.3.6获取运行时类实现的接口2.3.7获取运行时类声明的注解2.3.7获取运行时类所在的包2.3.8调用类的构造函数、操作类的属性、调用类中方法1Java

大家好,又见面了,我是你们的朋友全栈君。

1 Java反射机制概述

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。

在这里插入图片描述

Java反射机制提供的功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理

反射相关的主要API

  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造器

关于动态语言和静态语言

1、动态语言

是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。主要动态语言有:Object-C、C#、JavaSpript、PHP、Python、Erlang。

2、静态语言

与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!

2 反射及其使用

2.1 关于类 java.lang.Class

java中,Java源文件xxx.java经过javac.exe命令编译以后,会生成一个或多个字节码文件xxx.class,接着使用java.exe命令对某个字节码文件xxx.class进行解释运行,相当于将某个字节码文件加载到内存中,此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。简言之,Class的实例就对应着一个运行时类

哪些类型可以有Class对象?
(1)class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2)interface:接口
(3)[]:数组
(4)enum:枚举
(5)annotation:注解@interface
(6)primitive type:基本数据类型
(7)void

加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。

获取Class类实例的四种方式

public void test3() throws ClassNotFoundException { 
   
        // 1 调用运行时类的属性 .class
        Class clazz1 = Person.class;
        System.out.println(clazz1);

        // 2 通过运行时类的对象,调用getClass()
        Person person = new Person();
        Class clazz2 = person.getClass();
        System.out.println(clazz2);

        // 3 调用Class的静态方法 forName(String classPath)
        Class clazz3 = Class.forName("reflection.Person");
        System.out.println(clazz3);
        System.out.println(clazz3);

        // 4 使用类的加载器ClassLoader(不常用)
        ClassLoader classLoader = ReflectionDemo.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("reflection.Person");
        System.out.println(clazz4);

        // 每个类对应的Class的实例在运行过程中都是唯一的
        System.out.println(clazz2 == clazz1);//true
        System.out.println(clazz3 == clazz1);//true
        System.out.println(clazz4 == clazz1);//true
    }
class reflection.Person
class reflection.Person
class reflection.Person
class reflection.Person
class reflection.Person
true
true
true

Process finished with exit code 0

2.2 类的加载

2.2.1 类的加载过程

类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。

在这里插入图片描述

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

在这里插入图片描述

加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载的过程需要类加载器参与。

链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。

  • 验证:确保加载的类信息符合JVM规范,例如:以cafe开头,没有安全方面的问题。
  • 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
  • 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。

初始化

  • 执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
  • 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
  • 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。
/** * 第一步:加载,将A.class加载到内存中 * 第二步:链接结束后m=0 * 第三步:初始化后,m的值由 <clinit>() 方法执行决定。这个A的类构造器 <c0init>() 方法由类变量 * 的赋值和静态代码块中的语句按照顺序合并产生,类似于: * <clinit>(){ * m = 300; * m = 100; * } */
class A { 
   
    static { 
    m = 300; }
    static int m = 100;
}

public class ClassLoadingTest { 
   
    public static void main(String[] args) { 
   
        System.out.println(A.m);//100
    }
}

2.2.2 类加载器

类加载器作用是用来把类(class)装载进内存的。JVM规范定义了如下类型的类的加载器。

在这里插入图片描述

双亲委派机制/父类委托机制

当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的父加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。每一个层次的加载器都是如此。

采用这种机制主要是从安全方面考虑的,假设某人定义了一个与系统类重名的类,该类可能含有恶意或不健全的代码,如果先加载自定义类的话可能会影响程序的运行,所以只能先加载系统的类,由于每个类在运行时只存在一个Class类的实例,当系统类加载后,自定义类就不会被加载了。而实现这种加载顺序的方法就是双亲委派机制,先让顶层的类加载器加载相应的类,因为它们会先加载系统类库中的类,而自定义的类是由系统类加载器或自定义类加载器加载的,这样就保证了加载过程的安全性。

public class ClassLoaderTest { 
   
    public static void main(String[] args) { 
   
        // 系统类加载器
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);

        // 扩展类加载器
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1);

        // 引导类加载器。(引导类加载器无法直接获取,会输出null)
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2);
    }
}
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@677327b6
null

Process finished with exit code 0

2.3 反射的使用

代码目录结构

└─reflection1
      Creature.java
      MyAnnotation.java
      MyInteface.java
      Person.java
      Test1.java

public class Creature<T> implements Serializable { 
   
    private char sex_private;
    public double weight_public;

    private void breadth_private(){ 
   
        System.out.println("生物呼吸");
    }
    public void eat_public() { 
   
        System.out.println("生物吃东西");
    }
}
@Target({ 
   ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation { 
   
    String value() default "hello";
}
public interface MyInteface { 
   
    void info_public();
}
@MyAnnotation(value = "class_person")
public class Person extends Creature<String> implements Comparable<String>, MyInteface { 
   
    private String name_private;
    int age_default;
    public int id_public;

    public Person() { 
   }

    @MyAnnotation(value = "private_cons")
    private Person(String name_private) { 
   
        this.name_private = name_private;
    }

    Person(String name_private, int age_default) { 
   
        this.name_private = name_private;
        this.age_default = age_default;
    }

    @MyAnnotation
    private String show_private(String nation) throws IOException, ClassCastException { 
   
        System.out.println("我的国籍是:" + nation);
        return nation;
    }

    public String display_public(String interests, int years){ 
   
        return interests + ", " + years;
    }

    @Override
    public int compareTo(String o) { 
   
        return 0;
    }


    @Override
    public void info_public() { 
   
        System.out.println("我是一个人");
    }
}

2.3.1 创建运行时类的对象

   // 通过反射创建运行时类的对象
    public void test() throws Exception { 
   
        Class<Person> clazz = Person.class;
        /* 调用newInstance(),创建运行时类的对象。实际上对象还是通过调用类的无参构造函数创建的, 若没有无参构造函数,则报错。 要想此方法正常的创建运行时类的对象,要求: 1.运行时类必须提供空参的构造器 2.空参的构造器的访问权限得够。通常,设置为public。 在javabean中要求提供一个public的空参构造器。原因: 1.便于通过反射,创建运行时类的对象 2.便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器 */
        Person person = clazz.newInstance();
        System.out.println(person);
    }

2.3.2 获取运行时类的属性结构

	// 获取运行时类的属性结构
    public void getFields() { 
   
        Class<Person> clazz = Person.class;

        // 1 getFields():获取当前运行时类及其父类中声明为public访间权限的属性
        Field[] fields = clazz.getFields();
        for (Field field : fields) { 
   
            System.out.println(field);
        }
        System.out.println("********************");

        // 2 getDecLaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) { 
   
            System.out.println(declaredField);
        }
        System.out.println("*********************");

        int i = 0;
        for (Field declaredField : declaredFields) { 
   
            System.out.println("------属性 " + (++i) + ":" + declaredField);

            // 3 获取属性的访问修饰符
            int modifiers = declaredField.getModifiers();
            System.out.println(Modifier.toString(modifiers));

            // 4 获取属性的数据类型
            Class type = declaredField.getType();
            System.out.println(type.getName());

            // 5 获取变量名
            String name = declaredField.getName();
            System.out.println(name);
        }
    }
public int reflection1.Person.id_public
public double reflection1.Creature.weight_public
********************
private java.lang.String reflection1.Person.name_private
int reflection1.Person.age_default
public int reflection1.Person.id_public
*********************
------属性 1:private java.lang.String reflection1.Person.name_private
private
java.lang.String
name_private
------属性 2:int reflection1.Person.age_default

int
age_default
------属性 3:public int reflection1.Person.id_public
public
int
id_public

Process finished with exit code 0

2.3.3 获取运行时类的方法结构

	/** * 获取运行时类的方法结构。 * * @xxxAnnotation * 访问修饰符 返回值类型 方法名(参数列表) throws xxxException {} */
public void test2() { 

Class<Person> clazz = Person.class;
// 1 getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
Method[] methods = clazz.getMethods();
for (Method method : methods) { 

System.out.println(method);
}
System.out.println("********************************");
// 2 getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) { 

System.out.println(declaredMethod);
}
System.out.println("********************************");
int i = 0;
for (Method mtd : declaredMethods) { 

System.out.println("\n---------------方法 " + (++i) + ":" + mtd);
// 3 获取方法声明的注解
Annotation[] annotations = mtd.getAnnotations();
for (Annotation anno : annotations) { 

System.out.println(anno);
}
// 4 获取方法的访问修饰符
System.out.println(Modifier.toString(mtd.getModifiers()));
// 5 获取方法返回值类型
System.out.println(mtd.getReturnType().getName());
// 6 获取方法形参列表
Class[] parameterTypes = mtd.getParameterTypes();
if (parameterTypes.length > 0) { 

for (Class parameterType : parameterTypes) { 

System.out.print(parameterType + ", ");
}
System.out.println();
}
// 7 获取方法抛出的异常
Class[] exceptionTypes = mtd.getExceptionTypes();
if (exceptionTypes.length > 0) { 

for (Class exceptionType : exceptionTypes) { 

System.out.print(exceptionType + ", ");
}
}
}
}
public int reflection1.Person.compareTo(java.lang.String)
public int reflection1.Person.compareTo(java.lang.Object)
public void reflection1.Person.info_public()
public java.lang.String reflection1.Person.display_public(java.lang.String,int)
public void reflection1.Creature.eat_public()
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()
********************************
public int reflection1.Person.compareTo(java.lang.String)
public int reflection1.Person.compareTo(java.lang.Object)
private java.lang.String reflection1.Person.show_private(java.lang.String) throws java.io.IOException,java.lang.ClassCastException
public void reflection1.Person.info_public()
public java.lang.String reflection1.Person.display_public(java.lang.String,int)
********************************
---------------方法 1:public int reflection1.Person.compareTo(java.lang.String)
public
int
class java.lang.String, 
---------------方法 2:public int reflection1.Person.compareTo(java.lang.Object)
public volatile
int
class java.lang.Object, 
---------------方法 3:private java.lang.String reflection1.Person.show_private(java.lang.String) throws java.io.IOException,java.lang.ClassCastException
@reflection1.MyAnnotation(value=hello)
private
java.lang.String
class java.lang.String, 
class java.io.IOException, class java.lang.ClassCastException, 
---------------方法 4:public void reflection1.Person.info_public()
public
void
---------------方法 5:public java.lang.String reflection1.Person.display_public(java.lang.String,int)
public
java.lang.String
class java.lang.String, int, 
Process finished with exit code 0

2.3.4 获取运行时类的构造器结构

	// 获取运行时类的构造器结构
public void test3() { 

Class<Person> clazz = Person.class;
// 1 getConstructors():获取当前运行时类中声明public的构造器
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) { 

System.out.println(constructor);
}
System.out.println("*****************************");
// 2 getDeclaredConstructors():获取当前运行时类中声明的所有的构造器
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) { 

System.out.println(declaredConstructor);
}
}
public reflection1.Person()
*****************************
reflection1.Person(java.lang.String,int)
private reflection1.Person(java.lang.String)
public reflection1.Person()
Process finished with exit code 0

2.3.5 获取运行时类的父类信息

	public void test4() { 

Class<Person> clazz = Person.class;
// 1 获取父类名
Class<? super Person> superclass = clazz.getSuperclass();
System.out.println(superclass);
// 2 获取带泛型的父类
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(genericSuperclass);
// 3 获取带泛型的父类的 泛型类型
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
// 父类可能有多个泛型类型
for (Type actualTypeArgument : actualTypeArguments) { 

System.out.println(actualTypeArgument.getTypeName());
}
}
class reflection1.Creature
reflection1.Creature<java.lang.String>
java.lang.String
Process finished with exit code 0

2.3.6 获取运行时类实现的接口

	// 获取运行时类实现的接口
public void test5(){ 

Class<Person> clazz = Person.class;
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> c : interfaces) { 

System.out.println(c);
}
// 获取父类实现的接口
Class<?>[] interfaces1 = clazz.getSuperclass().getInterfaces();
for (Class<?> c : interfaces1) { 

System.out.println(c);
}
}
interface java.lang.Comparable
interface reflection1.MyInteface
interface java.io.Serializable
Process finished with exit code 0

2.3.7 获取运行时类声明的注解

	// 获取运行时类声明的注解
public void test6(){ 

Class<Person> clazz = Person.class;
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) { 

System.out.println(annotation);
}
}
@reflection1.MyAnnotation(value=class_person)
Process finished with exit code 0

2.3.7 获取运行时类所在的包

    // 获取运行时类所在的包
public void test7(){ 

Class<Person> clazz = Person.class;
Package aPackage = clazz.getPackage();
System.out.println(aPackage);
}
package reflection1
Process finished with exit code 0

2.3.8 调用类的构造函数、操作类的属性、调用类中方法

class Person { 

public String name_public;
private int age_private;
public Person() { 

}
private Person(String name_public) { 

this.name_public = name_public;
}
public Person(String name_public, int age_private) { 

this.name_public = name_public;
this.age_private = age_private;
}
private static void show_static(String name, int age) { 

System.out.println("my name is " + name + ", my age is " + age);
}
@Override
public String toString() { 

return "Person{" +
"name_public='" + name_public + '\'' +
", age_private=" + age_private +
'}';
}
public void show_public(){ 

System.out.println("我是一个人");
}
private String show_private(String name){ 

return name;
}
}
	// 通过常规方法创建一个类的对象,并对其进行操作
public void test1() { 

// 1 创建类对象
Person jack = new Person("jack", 88);
System.out.println(jack);
// 2 通过对象,调用类内部属性
jack.name_public = "jack1";
System.out.println(jack);
// 3 通过对象,调用其方法
jack.show_public();
// 在一个类外部,不能通过其对象调用内部的私有结构
}
Person{name_public='jack', age_private=88}
Person{name_public='jack1', age_private=88}
我是一个人
Process finished with exit code 0
	// 通过反射对类进行操作
public void test2() throws Exception { 

Class<Person> pClass = Person.class;
// 1 调用类的构造函数
/** * reflect.Constructor<T> getConstructor(@Nullable Class<?>... parameterType) * 参数:构造函数的参数列表 */
Constructor<Person> cons_public = pClass.getConstructor(String.class, int.class);
Person lisa = cons_public.newInstance("lisa", 33);
System.out.println(lisa);
// 2 操作类内部属性
/** * reflect.Field getField(@NonNls @NotNull String name) * 参数:属性名 * * void set(Object obj, Object value) * 参数一:指明设置哪个对象的属性 * 参数二:将此属性值设置为多少 */
Field name_public = pClass.getField("name_public");
name_public.set(lisa, "lisa1");
System.out.println(lisa);
// 3 调用类中方法
/** * reflect.Method getMethod(@NonNls @NotNull String name, @Nullable Class<?>... parameterTypes) * 参数一:方法名 * 参数二:形参列表,若有多个参数,则写多个 * * Object invoke(Object obj, Object... args) * 参数一:方法的调用者 * 参数二:给方法形参赋值的实参,若有多个参数,则写多个 * 返回值:被调用方法的返回值。如:原方法返回 18,则invoke返回 18;原方法返回 "abc",则invoke返回 "abc"…… */
Method show_public = pClass.getMethod("show_public");
show_public.invoke(lisa);
// ---------通过反射,操作类内部的私有结构-----------------
// 1 调用私有构造方法
Constructor<Person> cons_private = pClass.getDeclaredConstructor(String.class);
cons_private.setAccessible(true);
Person michael = cons_private.newInstance("michael");
System.out.println(michael);
// 2 操作类的私有属性
Field age_private = pClass.getDeclaredField("age_private");
age_private.setAccessible(true);
age_private.set(michael, 55);
System.out.println(michael);
// 3 调用类的私有方法
Method show_private = pClass.getDeclaredMethod("show_private", String.class);
show_private.setAccessible(true);
String res = (String) show_private.invoke(michael, "我的名字是:michael");
System.out.println(res);
// 4 调用静态方法
Method show_static = pClass.getDeclaredMethod("show_static", String.class, int.class);
show_static.setAccessible(true);
show_static.invoke(Person.class, "jim", 20);
}
Person{name_public='lisa', age_private=33}
Person{name_public='lisa1', age_private=33}
我是一个人
Person{name_public='michael', age_private=0}
Person{name_public='michael', age_private=55}
我的名字是:michael
my name is jim, my age is 20
Process finished with exit code 0
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/157087.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • sqlyog激活成功教程版_sqlyog10.0安装教程

    sqlyog激活成功教程版_sqlyog10.0安装教程链接:https://pan.baidu.com/s/1N3ufWDe-CKj4QvNIz8vXpA提取码:95hm直接安装接着用压缩白内的文档注册码注册即可使用。

  • [机器学习] 实验笔记 – 表情识别(emotion recognition)

    本文主要整理自笔者在表情识别(emotionrecognition)研究上的实验笔记资料,给出了表情识别常用的数据库,论文资料,识别方法,评价指标,以及笔者的实验笔记和实验结果。与读者分享,欢迎讨论。

  • 小型企业的网络拓扑结构设计

    小型企业的网络拓扑结构设计小型企业的网络拓扑结构设计一、设计目的企业局域网的最终目标是建设整个单位的互联、统一、高效、实用、安全的局域网络,近期可支持上百个,远期至少可支持上午个并发用户,提供广泛的资源共享(包括硬件、软件和信息资源共享)。网络结构清楚、布线合理、充分考虑房间分布;局域网性能稳定、安全;软、硬件结合良好,公司日常办公需要,方便资源共享、游览有良好的兼容性和可扩展性,具备单位局域网与其他单位局域网互连,并…

  • 下载安装包并安装使用_openiv安装教程

    下载安装包并安装使用_openiv安装教程VS2022版来了,VisualStudio2022最新版安装教程(数千字图文详解),一步步教会你如何安装并运行VS2022,以及背景图设置。

    2022年10月12日
  • 视觉SLAM——特征点法与直接法对比以及主流开源方案对比 ORB LSD SVO DSO

    视觉SLAM——特征点法与直接法对比以及主流开源方案对比 ORB LSD SVO DSO单目视觉SLAM可以根据其前端视觉里程计或是后端优化的具体实现算法进行分类:前端可以分为特征点法与直接法,后端可以分为基于滤波器和基于非线性优化。其中在后端上目前已经公认基于非线性优化的方法在同等计算量的情况下,比滤波器能取得更好的结果。而前端的两种方法则各有优劣。本文将具体分析直接法相较于特征点法的优劣处,并具体介绍目前主流的开源方案,以供大家参考。

  • 常用放射性核素表_X射线核素的名称

    常用放射性核素表_X射线核素的名称常用放射性核素表原子序数及元素名称核素符号半衰期衰变类型括号内为每100次衰变中发生的次数主要带电粒子及其能量(MeV)括号内为平均100次衰变中发射的次数主要γ线能量(MeV)括号内为平均100

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号