Java教程

JAVA基础7 反射

本文主要是介绍JAVA基础7 反射,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
  • 反射

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

在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。
在执行程序(java.exe)时候,将字节码文件读入JVM中--->这个过程叫做类的加载。然后在内存中对应创建一个java.lang.Class对象-->这个对象会被放入字节码信息中,这个Class对象,就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口。
所以:我们可以通过这个对象看到类的结构,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称之为反射
这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

说明:在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。
如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。

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

所以Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动
态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。
Java的动态性让编程的时候更加灵活!

 

 

  1.  获取字节码信息:
package com.zhaoss.test02;
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //案例:以Person的字节码信息为案例
        //方式1:通过getClass()方法获取
        Person p = new Person();
        Class c1 = p.getClass();
        System.out.println(c1);
        //方式2:通过内置class属性:
        Class c2 = Person.class;
        System.out.println(c2);
        System.out.println(c1==c2);
        //注意:方式1和方式2  不常用
        //方式3:--》用的最多:调用Class类提供的静态方法forName
        Class c3 = Class.forName("com.zhaoss.test02.Person");
        //方式4:利用类的加载器(了解技能点)
        ClassLoader loader = Test.class.getClassLoader();
        Class c4 = loader.loadClass("com.zhaoss.test02.Person");
}

 

Class的具体实例:

类:外部类,内部类

接口

注解

数组

基本数据类型

void

public class Demo {
    public static void main(String[] args) {
        /*
        Class类的具体的实例:
        (1)类:外部类,内部类
        (2)接口
        (3)注解
        (4)数组
        (5)基本数据类型
        (6)void
         */
        Class c1 = Person.class;
        Class c2 = Comparable.class;
        Class c3 = Override.class;
        int[] arr1 = {1,2,3};
        Class c4 = arr1.getClass();
        int[] arr2 = {5,6,7};
        Class c5 = arr2.getClass();
        System.out.println(c4==c5);//结果:true .同一个维度,同一个元素类型,得到的字节码就是同一个
        
        Class c6 = int.class;
        Class c7 = void.class;
    }
}

提供一个丰富的类备用:

//作为一个父类
public class Person implements Serializable {
    //属性
    private int age;
    public String name;
    //方法
    private void eat(){
        System.out.println("Person---eat");
    }
    public void sleep(){
        System.out.println("Person---sleep");
    }
}
//Student作为子类
@MyAnnotation(value="hello")
public class Student extends Person implements MyInterface{
    //属性:
    private int sno;//学号
    double height;//身高
    protected double weight;//体重
    public double score;//成绩
    //方法:
    @MyAnnotation(value="himethod")
    public String showInfo(){
        return "我是一名三好学生";
    }
    public String showInfo(int a,int b){
        return "重载方法====我是一名三好学生";
    }
    private void work(){
        System.out.println("我以后会找工作--》成为码农  程序员 程序猿  程序媛");
    }
    void happy(){
        System.out.println("做人最重要的就是开心每一天");
    }
    protected int getSno(){
        return sno;
    }
    //构造器
    public Student(){
        System.out.println("空参构造器");
    }
    private Student(int sno){
        this.sno = sno;
    }
    Student(int sno,double weight){
        this.sno = sno;
        this.weight = weight;
    }
    protected Student(int sno,double height,double weight){
        this.sno = sno;
    }
    @Override
    @MyAnnotation(value="hellomyMethod")
    public void myMethod() {
        System.out.println("我重写了myMethod方法。。");
    }
    @Override
    public String toString() {
        return "Student{" +
                "sno=" + sno +
                ", height=" + height +
                ", weight=" + weight +
                ", score=" + score +
                '}';
    }
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
/*
@Target:定义当前注解能够修饰程序中的哪些元素
@Retention:定义注解的声明周期
 */
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value();//属性
}
public interface MyInterface {//自定义的接口
    //随便定义一个抽象方法:
    void myMethod();
}

获取构造器创建对象

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test01 {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取字节码信息:
        Class cls = Student.class;
        //通过字节码信息可以获取构造器:
        //getConstructors只能获取当前运行时类的被public修饰的构造器
        Constructor[] c1 = cls.getConstructors();
        for(Constructor c:c1){
            System.out.println(c);
        }
        System.out.println("-------------------");
        //getDeclaredConstructors:获取运行时类的全部修饰符的构造器
        Constructor[] c2 = cls.getDeclaredConstructors();
        for(Constructor c:c2){
            System.out.println(c);
        }
        System.out.println("-------------------");
        //获取指定的构造器:
        //得到空构造器
        Constructor con1 = cls.getConstructor();
        System.out.println(con1);
        //得到两个参数的有参构造器:
        Constructor con2 = cls.getConstructor(double.class, double.class);
        System.out.println(con2);
        //得到一个参数的有参构造器:并且是private修饰的
        Constructor con3 = cls.getDeclaredConstructor(int.class);
        System.out.println(con3);
        //有了构造器以后我就可以创建对象:
        Object o1 = con1.newInstance();
        System.out.println(o1);
        Object o2 = con2.newInstance(180.5, 170.6);
        System.out.println(o2);
    }
}

 

这篇关于JAVA基础7 反射的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!