Java基础知识总结-注解和反射

学习渠道:B站狂神说Java

注解

注解的分类
1.内置注解
@Override:java.lang.Override
表示一个方法声明要重写超类中的一个方法声明。
@Deprecated:java.lang.Deprecated
属性,类,表示过时的元素,通常它是有风险的,或者有更好的选择。
@SuppressWarnings:java.lang.SuppressWarnings
可以用在类或者方法,属性上用来使编译时的警告信息不显示它是有参数的例如:
@SuppressWarnings(“all”),@SuppressWarnings(“unchecked”),@SuppressWarnings({“uncheked”,“deprecation”})

2.元注解
元注解作用就是对于其他注解进行说明,这些注解可以再java.lang.annotation包中找到.
@Target:用于描述注解的使用范围(属性,方法,类)
@Retention:表示注解的生命周期(源码(SOURCE)<编译(CLASS)<运行时(RUNTIME))
@Document:说明该注解被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解

3.自定义注解
@interface 修饰的类就是注解,然后可以由元注解来标明使用的细节
注意:如果注解中只有一个参数且参数名为value时,在使用时可以不写参数名直接填参数。其他情况下有参数并且没有默认值是,使用必须填写参数名和参数内容。

元注解和自定义注解的使用例子

@Annotation1("a1")//value一个参数可以不写参数名
@Annotation2(name = "a2")//没有默认值的参数必须赋值
public class Annotation {

}

//元注解设置适用范围
@Target({ElementType.TYPE,ElementType.METHOD})
//元注解Retention 设置有效范围(源文件,编译,运行)
@Retention(RetentionPolicy.RUNTIME)
@interface Annotation1{ //写在类中的注解不能有public
    //当注解只有一个参数且参数名为value时可以省略不写
    String value();
}

@Target({ElementType.TYPE,ElementType.METHOD})
@interface Annotation2{
    String name();
    int age() default 18;
    String[] students() default {"1","2"};
}

反射

动态语言和静态语言
动态语言是一类在运行时可以改变其结构的语言:例如新的函数,对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。简单的讲就是在运行时代码能够根据某些条件改变自身结构
主要的动态语言:object-C、C#、JavaScript、PHP、Python等
静态语言:运行时结构不可变的语言就是静态语言。比如Java、C、C++。
Java不是动态语言,但Java被称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程的时候更加灵活。

Class类
加载完类之后在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了完整的类的结构信息。
Class本身就是一个类
Class对象只能有系统建立对象
一个加载类在JVM中只会有一个.class文件
一个Class对象对应的是一个加载到JVM的一个.class文件
每个类的实例都会记得自己是由哪个class类生成
通过Class可以完整的得到一个类中的所有被加载的结构(反射的核心)
Class类是Reflection的根源,针对任何你想动态加载、运行的类、唯有先获得相应的class对象

反射(Reflection)
反射是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。反射可以通过对象来获取Class类的完整结构。这个对象就是一面镜子,透过镜子看类结构所以称为反射。
在这里插入图片描述
Class类的常用方法
在这里插入图片描述
获取Class对象的方式

public class ReflectionTest {
    public static void main(String[] args) throws ClassNotFoundException {
        User u1 = new User();
        Class c1 = u1.getClass();
        Class c2 = Class.forName("reflection.User");
        //类的实例化对象和Class静态方法获取的class对象是同一个class对象
        //类在被加载时会生成唯一一个calss对象在堆中。
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println("------------------------------------------------");
        //获取class对象的方法
        //通过类名直接获取
        Class c3 = Studnet.class;
        System.out.println("student的class:"+c3.hashCode());
        //通过具体路径获取
        Class c4 = Class.forName("reflection.Studnet");
        System.out.println("student的class:"+c4.hashCode());
        //通过具体的对象获取
        Studnet studnet = new Studnet();
        Class c5 = studnet.getClass();
        System.out.println("student的class:"+c5.hashCode());
        //JDK一些基本数据类型的包装类可以通过type直接获取
        Class c6 = Integer.TYPE;
        System.out.println("Integer包装类的class:"+c6);
        //通过子类clss获取父类对象的class
        Class c7 = c3.getSuperclass();
        System.out.println("student的父类User的class:"+c7.hashCode());

        Class cl1 = int.class;
        Class cl2 = Integer.class;
        System.out.println(cl1.hashCode());
        System.out.println(cl2.hashCode());//结果是不一样
    }
}

具体的一些常用方法
(下面的例子主要介绍了怎么通过class来获取类的结构)

class User{
    private String name ;
    private String id;
    private int age;
    public User() {
    }
    public User(String name, String id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }
    private User(Studnet a){

    }

	get.... set.....
}

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("reflection.User");

        String name1 = c1.getName();
        System.out.println("带包名的名称"+name1);
        String simpleName = c1.getSimpleName();
        System.out.println("不带包名的名称"+simpleName);

        /*
        类的属性
         */
        //获取类的属性
        Field[] fields = c1.getFields();//获取类的public属性
        for (Field field : fields) {
            System.out.println(field);
        }

        fields = c1.getDeclaredFields();//获取类的所有属性
        for (Field field : fields) {
            System.out.println("所有属性"+field);
        }

        Field name = c1.getDeclaredField("name");//获取指定的属性包括私有的和公共的
        System.out.println(name);

        /*
        类的方法
         */
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("public修饰的方法包括父类的"+method);
        }

        methods = c1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("自己类全部的方法"+method);
        }

        Method method = c1.getMethod("getName", null);
        System.out.println(method);
        method = c1.getDeclaredMethod("setName", String.class);
        System.out.println(method);

        /*
        构造方法
         */

        Constructor[] constructors = c1.getConstructors();//公共的构造方法
        for (Constructor constructor : constructors) {
            System.out.println("公共的构造方法"+constructor);
        }

        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("所有的构造方法"+constructor);
        }


    }
}

通过类的结构来创建类对象,调用方法,属性。

public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Class c1 = Class.forName("reflection.User");//获取class对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, String.class, int.class);//获取有参构造方法
        User user = (User) constructor.newInstance("学习没个头", "001", 18);//执行有参构造方法
        System.out.println(user);

        User user1 = (User) c1.newInstance();//执行无参构造方法
        user1.setName("学习头在哪");
        Field id = c1.getDeclaredField("id");//获取id属性
        id.setAccessible(true);
        id.set(user1,"002");//指定对象来设置属性(需要属性权限为public若为私有的需要调用属性的setAccessible设置为true)
        Method setAge = c1.getDeclaredMethod("setAge", int.class);//获取方法
        setAge.setAccessible(true);
        setAge.invoke(user1,19);//指定对象来设置使用方法(需要方法权限为public若为私有的需要调用方法的setAccessible设置为true)
        System.out.println(user1);
    }
}

setAccessible
这个是控制结构安全状态的方法,若是true则安全状态接触,可以操作private修饰的属性,方法,并且可以减少处理时间。若为false(默认)则private修饰的属性和方法不能通过结构进行操作。

性能
对象操作>不加安全状态的反射结构操作>加安全状态的接口操作。

还有class对象操作泛型,注解需要补充

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值