Java反射

类对象

类的对象:基于某个类new出来的对象,也称为实例对象
类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
每一个类加载到内存之后,都对应一个Class对象,每个类有且只有一个
JVM参数:-verbose:class显示类的加载过程
获取类对象

  1. 通过类的对象,获取类对象
  • Student s=new Student();
  • Class<?> c=s.getClass();
  1. 通过类名获取类对象
  • Class c=类名.class;
  1. 通过静态方法
  • Class c=Class.forName(“包名.类名");

反射常用操作

  • public String getName();
  • public Package getPackage()
  • public Class<? super T> getSuperclass()
  • public Class<?>[] getInterfaces()
  • public Constructor<?>[] getConstructors()
  • public T newInstance()
  • public Method[] getMethods()
  • public Field [] getFields() 获取属性
    Person类,以下操作都用它
package net;

import java.io.Serializable;

/**
 * Person类
 * @author wgy
 *
 */
public class Person implements Serializable,Cloneable{
    //姓名
    private String name;
    //年龄
    private int age;

    public Person() {
        System.out.println("无参构造执行了...");
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
        System.out.println("带参构造方法执行了...");
    }


    //吃
    public void eat() {
        System.out.println(name+"正在吃东西......");
    }


    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    //带参的方法
    public void eat(String food) {
        System.out.println(name+"开始吃...."+food);
    }

    //私有的方法
    private void privateMethod() {
        System.out.println("这是一个私有方法");
    }

    //静态方法
    public static void staticMethod() {
        System.out.println("这是一个静态方法");
    }
}

一、获取类的名字、包名、父类、接口

package net;

import java.util.ArrayList;
import java.util.Arrays;

public class TestPerson {
    public static void main(String[] args) throws Exception{
        reflectOpen1();
    }

    public static void reflectOpen1() throws Exception {
        Class<?> class1=Class.forName("net.Person");
        System.out.println(class1.getName());
        System.out.println(class1.getPackage().getName());
        System.out.println(class1.getSuperclass().getName());
        Class<?>[] classes= class1.getInterfaces();
        System.out.println(Arrays.toString(classes));
        System.out.println(class1.getSimpleName());
        System.out.println(class1.getTypeName());
    }
}

net.Person
net
java.lang.Object
[interface java.io.Serializable, interface java.lang.Cloneable]
Person
net.Person

二、获取类中的构造方法,创建对象

public static void reflectOpen2() throws Exception{
        Class<?> class1=Class.forName("net.Person");
        //获取类的构造方法
       Constructor<?>[] constructors= class1.getConstructors();
       for (  Constructor<?> constructor:constructors)
       {
           System.out.println(constructor.toString());
       }
       Constructor<?> constructor=class1.getConstructor();
       Person zhangshan=(Person)constructor.newInstance();
        System.out.println(zhangshan.toString());
        //简便方法
        Person person=(Person)class1.newInstance();
        System.out.println(person.toString());

        Constructor<?> constructor1=class1.getConstructor(String.class,int.class);
        Person xiaoli=(Person)constructor1.newInstance("小李",20);
        System.out.println(xiaoli.toString());
    }
}

public net.Person()
public net.Person(java.lang.String,int)
无参构造执行了…
Person [name=null, age=0]
无参构造执行了…
Person [name=null, age=0]
带参构造方法执行了…
Person [name=小李, age=20]

三、使用反射获取类中的方法并调用方法

  public static void reflectOpen3() throws Exception {
        //获取类对象
        Class<?> class1=Class.forName("net.Person");
        //公开和继承的父类的方法
        Method[] methods=class1.getMethods();
        for (Method m :methods) {
            System.out.println(m.toString());
        }
        System.out.println("=========");
        //可获取私有方法,不包含继承的
        Method[] methods1=class1.getDeclaredMethods();
        for (Method m :methods1) {
            System.out.println(m.toString());
        }
        Method method=class1.getMethod("eat");
        Person person=(Person)class1.newInstance();
        method.invoke(person);
        Method method1=class1.getMethod("toString");
      ;
        System.out.println( method1.invoke(person));
        System.out.println("======");
        Method method2=class1.getMethod("eat", String.class);
        method2.invoke(person,"牛奶");
        Method method3=class1.getDeclaredMethod("privateMethod");
        //私有方法设置访问权限失效
        method3.setAccessible(true);
        method3.invoke(person);

        //静态
        Method method4=class1.getMethod("staticMethod");
        method4.invoke(null);

    }

四、使用反射实现可以调用任何对象方法的通用方法

 public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception {
        Class<?> c =obj.getClass();
        Method method= c.getMethod(methodName,types);
        return method.invoke(obj,args);
    }

五、获取类中的属性

public static void reflectOpen4() throws Exception {
	Class<?> class1=Class.forName("net.Persom");
	Field field=class1.getField("name");
	field.setAccessible(true);
	Person person=class1.newInstance();
	field.set(person,"张三");
	System.out.println(person.toString());

	
}

设计模式

一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。简单理解:特定问题的固定解法
好处:使用设计模式是为了可重用代码、让代码更容易被他人理解 、保证代码可靠性、重用性。

一、工厂设计模式

工厂模式主要负责对象创建的问题。
开发中有一个非常重要的原则“开闭原则”,对扩展开放,修改关闭。
可通过反射进行工厂模式的设计,完成动态的对象创建

public class UsbFactory {
    public static Usb createUsb(String type) throws Exception {
        Usb usb=null;
        Class<?>  class1=Class.forName(type);
        Usb usb1= (Usb) class1.newInstance();
        return usb;
    }
}

二、单例模式

只允许创建一个该类的对象

1.饿汉式:

类加载时创建,天生线程安全

public class SingleTon {
    private static final SingleTon instance=new SingleTon();
    private SingleTon(){}
    public SingleTon getInstance(){
        return instance;
    }
}

多线程情况下,拿到的对象都是同一个

2.懒汉式

使用时创建,线程不安全,加同步

package Single;

public class SingleTon2 {
    private static  SingleTon2 singleTon2=null;
    private SingleTon2(){}
    public static synchronized SingleTon2 getInstance(){
        if(singleTon2==null){
            singleTon2=new SingleTon2();
        }
        return singleTon2;
    }
}

多线程下,不加synchronized打印的hashCode会不一样,线程不安全,或者同步代码块也可以,其中的锁应该是类.class
为提高效率,可以在外层加一个判断

3.懒汉式(使用时创建,线程安全)

package Single;

import org.omg.CORBA.PUBLIC_MEMBER;
import sun.security.rsa.RSASignature;

public class SingleTon3 {
    private SingleTon3(){
    }
    //不使用不会执行
    private static class Holder{
        static SingleTon3 singleTon3=new SingleTon3();
    }
    public static SingleTon3 getInstance(){
        return Holder.singleTon3;
    }
}

枚举

什么是枚举

引用类型,枚举是一个规定了取值范围的数据类型;
枚举遍历不能使用其他数据,只能使用枚举中常量赋值,提高程序安全性
定义使用enum关键字
要求:必须包含常量,也可以包含属性和方法,私有构造方法
枚举常量必须在前面,多个常量之间使用,隔开,最后分号,可写可不写
实际就是终止类,继承了Enum抽象类
常量是当前静态类型的常量

package Single;
/*
必须包含常量,也可以包含属性和方法,私有构造方法
枚举常量必须在前面,多个常量之间使用,隔开,最后分号,可写可不写
 */
public enum Gender {
    MALE,FEMALE;
    private String value;
    private Gender(){
    }
    public void show(){};
}

注解

什么是注解

代码里的特殊标记,程序可以读取注解,一般用于替代配置文件

开发人员可以通过注解告诉类如何运行

可以通过反射技术去得到类里面的注解,以决定怎么运行类

常见注解

@Override
@Deprecated(过时)
定义注解使用@interface关键字,注解中只能包含属性

定义注解

public @interface MyAnnotation {
    //属性类似方法
    String name() default "张三";
    int age() default 20;
}


public class Person {
    @MyAnnotation(name="张三",age=20)
    public void show(){
    }
}

注解的属性类型

  • String
  • 基本数据类型
  • Class类型
  • 注解类型
  • 以上类型的一维数组

注解的本质

就是接口
在这里插入图片描述

反射获取注解信息

元注解

用来描述注解的注解

在这里插入图片描述

@Retention(value = RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    //属性类似方法
    String name() default "张三";
    int age() default 20;
    String sex();
}

@Target:指定注解修饰类的哪个成员
@Target(value = {ElementType.TYPE,ElementType.METHOD})//只能用在类上面,方法上面

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值