Java学习-注解和反射

注解

java.Annotation

Annotation的作用:可以呗其他程序读取

Annotation的格式

  • 注解是:@注释名 在代码中存在,还可以添加一些参数

    ​@SuppressWarnings(values="unchecked")

  • 通过反射,可以访问数据。

内置注解

@override:定义在java.lang.Override中,此注解只适用于修饰方法,标识一个方法声明打算重写父类的另一个方法。

@Deprecated:定义在java.lang.Deprecated中,此方法用于修饰方法,类,属性。表示废弃元素

@SuppressWarings:定义在java.lang.SuppressWarings中,用来抑制编译时的警告信息。

  • 此方法需要传入参数。
public class Demo01 extends Object {

    //重写的注解
    @Override
    public String toString() {
        return super.toString();
    }

    //不推荐使用的注解,但是可以使用
    @Deprecated
    public static void test() {
        System.out.println("Deprecated");
    }

    @SuppressWarnings("all")
    public static void test2() {
        ArrayList arrayList = new ArrayList();
    }

    public static void main(String[] args) {
        test();
    }
}

元注解

元注解就是负责注解其他的注解,Java定义了四个标准的meta-annotation类型,他们用来提供对其他annotation类型操作说明

可以从java.lang.annotation中找到(@Target,@Retention,@Docimented,@Inherited

@Target:用于描述注解的使用范围({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}

@Retention:标识需要在什么级别保存该注解信息,用于描述注解的生命周期(SOURCE<CLASS<RENTIME

@Docimented:说明注解将被包含在javadoc中

@Inherited:说明子类可以继承父类中的该注解

自定义注解

使用@interface自定义注解

格式

public @interface MyAnnotation
{
}
public class Demo02 {
    //注解可以显示的复制,如果没有默认值,就一定要注解赋值
    @MyAnnotation(name = "nice",schools = {"1234","2314"})
    public void test(){}
@MyAnnotation2("sdf")
    public void test2(){}
}

@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value =RetentionPolicy.RUNTIME)
@interface MyAnnotation
{
    //注解的参数:参数类型 参数名();
    String name() default "";
    int age() default 0;
    int id() default -1;//代表不存在。
    String[] schools() default {"erq","asds"};
}

@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value =RetentionPolicy.RUNTIME)
@interface MyAnnotation2
{
    //注解的参数:参数类型 参数名();
    String value() default "";
}

反射

java.Reflection

反射机制允许程序在执行期间借助Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性级方法

Class c= Class.forName("java.lang.String")

获得反射对象

public class Demo03 {

    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象
        Class c1 = Class.forName("com.darker.demo01.User");
        Class c2 = Class.forName("com.darker.demo01.User");
        Class c3 = Class.forName("com.darker.demo01.User");
        //一个类在内存中只有一个Class对象
        //一个类被加载后,类的整个结构都会被装在Class对象中
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());

    }
}

Class对象

方法名 功能说明
static ClassforName(String name) 返回指定类名name的Class对象
Object newInstance() 调用缺省构造函数,返回Class对象的一个实例
getName() 返回此Class对象锁标识的实体(类、接口、数组类或void)的名称
Class getSuperClass() 返回此Class对象的父类的Class对象
Class[] getinterfaces() 获取此Class对象的接口
ClassLoader getClassLoader() 返回该类的类加载器
Constructor[] getConstructors() 返回一个包含某些Constructor对象的数组
Method getMethod(String name,Class...T) 返回一个Method对象,此对象的类型类paramaType
Field[] GetDeclaredFields() 返回Field对象的一个数组

获取Class对象

public class Demo04 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是"+person.name);

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        //方式二:forname获得
        Class c2 = Class.forName("com.darker.demo01.Student");
        System.out.println(c2.hashCode());
        //方式三:通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        //方式四,基本内置类型的包装类都有一个type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4.hashCode());

        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}

class Person{
    public String name;

    public Person() {
    }

    Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person
{
    public Student() {
        this.name = "学生";
    }
}
class Teacher extends Person
{
    public Teacher() {
        this.name = "老师";
    }
}

哪些类型有Class对象

class:外部类,成员内部类,静态内部类,局部内部类,局部内部类,匿名内部类。

interface:接口

[]:数组

enum:枚举

annotation:注解@interface

primitive type:基本数据类型

void

class内存分析

public class Demo05 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);
        /*
        1.加载到内存,会产生一个类的对应的Class对象
        2.链接,链接后m=0
        3.初始化
        <cinit>(){
        System.out.println("A类静态代码块初始化");
        m = 300;
         m = 100;
        }
        */
    }
}
class A{
    static {
        System.out.println("A类静态代码块初始化");
        m=300;
    }
    static int m = 100;
    public A()
    {
        System.out.println("A类的无参构造初始化");
    }
}

打印结果:

A类静态代码块初始化
A类的无参构造初始化
100

类的初始化

类的主动引用(一定会发生类的初始化)

  • 当虚拟机启动,先初始化main方法所在的类
  • new一个类对象
  • 调用静态成员(除了final常量)和静态方法
  • 使用java.lang.reflect包的方法惊醒反射调用
  • 当初始化一个类,如果其父类没有初始化,咋会初始化它的父类

类的被动引用(一定不会发生类的初始化)

  • 通过数组定义类引用
  • 引用常量触发此类的初始化(常量在链接阶段就存入调用类的常量池中)
  • 当访问一个静态域,只有真正声明这个域的类才会被初始化。如:通过子类调用父类的静态变量。

类加载器

引导类加载器

扩展类加载器 ExtClassLoader 负责jre/lib/ext目录下的jar包或者-D java.ext.dirs指定目录下的jar包装入工作库

系统类加载器 AppClassLoader 负责java -classpath或-D java.class.path所指的目录下的类与jar包装如工作库,是最常用的加载器

public class Demo06 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器--》扩展类接在其
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父类加载器--》根加载器(c/C++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        ClassLoader classLoader = Class.forName("com.darker.demo01.Demo06").getClassLoader();
        System.out.println(classLoader);
        //如何获取系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
    }
}

获取类的信息

public class Demo07 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class aClass = Class.forName("com.darker.demo01.User");
        //获得类的名字
        System.out.println("获得类的名字");
        //获得包名+类名
        System.out.println(aClass.getName());
        //获得类名
        System.out.println(aClass.getSimpleName());

        //获得类的属性
        System.out.println("获得类的属性");
        //只能找到public属性
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //能找到全部属性
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }

        //获得类的方法
        System.out.println("获得类的方法");
        //获得本类和父类的所有public方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("=========================");
        //获得本类所有方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
    }
}

通过反射操作类

public class Demo08 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
        Class c1 = Class.forName("com.darker.demo01.User");
        //构造一个对象
        User user1 = (User) c1.newInstance();
        System.out.println(user1);

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        Object user2 = constructor.newInstance("Darker", 1, 22);
        System.out.println(user2);
        //通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke激活。(对象,“方法值”)
        setName.invoke(user3, "darkerJO");
        System.out.println(user3);
        //通过反射操作属性
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //不能直接操作私有属性,需要关闭程序的安全监测,属性或方法的setAccessible(true)
        name.setAccessible(true);
        name.set(user4, "DarkerGuo");
        System.out.println(user4);
    }
}
(0)

相关推荐

  • 关于Java你不知道的那些事之Java注解和反射

    作者:轻狂书生FS https://blog.csdn.net/LookForDream_/ 前言 我们在实际的工作中,项目使用的框架中会经常遇到注解和反射.但是我们大部分同学都仅仅限于知道这是注解和 ...

  • Java基础之三个修饰符

    三个关键字 抽象的(abstract) 静态(static) 最终的(final) 一.抽象 1.1 什么是抽象 似是而非的,像却又不是:具备某种对象的特征,但不完整. 二. 抽象的(abstract ...

  • Java学习-多线程

    多线程 任务(Task).进程(Process).线程(Thread) 进程的创建 1.继承Thread类 自定义线程类继承Thread类 重写run()方法,编写线程执行体 创建线程对象,调用sta ...

  • Java学习-Mybatis

    Mybatis Maven依赖: <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependenc ...

  • Java 学习笔记

    您对计算机(电脑)有了解吗? 计算机组成 系统软件 直接和硬件交互的软件叫系统软件,例如 win7.win8.Linux.mac等操作系统 应用软件 通常在运行在系统软件上,也就是在系统软件上开发的软 ...

  • Java学习-126.2048代码

    本篇帖的是按钮的代码. 因为按钮比较多,包括菜单项的动作,为了区分,我用了两个内部类来实现这两部分代码. //本类是Game_2048类的内部类,用来实现上.下.左.右四个按钮,以及重新开始和退出游戏 ...

  • Java学习—125.2048代码

    本篇帖的是部分动作代码. 每个方法前都有注释说明本方法的功能. //随机选取一个位置,并填入数字2.如果此位置中已有数字,那么换一个位置. public void rule(){ x=ran.next ...

  • Java学习—124.2048代码

    游戏的主界面的代码在类game_2048中. 本类主要包括两个方面: 一是布局. 二是动作,按钮的动作. 其中,动作又有菜单动作,按钮动作.而按钮动作又有多方面,在下一篇的代码中会有注释说明. 本篇帖 ...

  • Java学习—123.2048小游戏

    好久又没出现了,还好后台也没几条信息,我也不至于很愧疚,只是人气不太旺盛,好尴尬 最近稍微有点忙,也是自己放松了一下,哈哈...... 抱歉一下,之前给我信息的各位亲,由于时间有点久,我就不一一回复了 ...

  • Java学习—问题

    上个月参加了一个考试,然后面试,准备.折腾了好久时间,身心俱疲,也没有更新公众号,后台有好多留言,但时间已过,我已经回不了了 请各位见谅...... 在后台看到一个小伙伴的留言,要解决一个问题, 本篇 ...