java放弃第一步

Java从零到放弃

环境搭建

下载地址https://www.jetbrains.com/idea/download/#section=windows

取消大小写敏感

image-20210413102118467

添加中文语言插件

image-20210413102937530

输出hello world

package com;

public class hello {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

常用的快捷键

F7步入 F8步过 F9运行到下一个断点 ALT+F8评估表达式 Ctrl + F查找字符串

双击Shift 查找任何内容,可搜索类、资源、配置项、方法等,还能搜索路径

Ctrl + N 按类名搜索类

Ctrl + F12 查看当前类结构

Ctrl + H 查看类的层次关系

Alt + F7 查找类或方法在哪被使用

基础知识

JAVA反射机制

反射的概念,就是在动态运行状态的时候,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能调用它的任意方法和属性(包括私有),即类对我们而言是完全透明的

想要使用反射机制,必须先获取到该类的字节码文件对象.class,通过字节码文件对象,都能够通过该类中的方法获取到我们想要的所有信息,每一个字节码文件也就对应着一个class类型的对象,获取字节码文件对象的三种方式:

Class c1 = Class.forName("类");
//通过Class的静态方法forName,获取一个类的字节码文件对象,此时仍处于源文件阶段
Class c2 = Person.class;
//当类被加载成.class文件时,Person类变成了.class,在获取该字节码文件对象,也是获取自己,处于字节码阶段
Class c3 = p.getClass();
//通过类的实例获取类的字节码对象,此时该类处于创建对象阶段

比如:

public class User {
    private String name;
    private int age;
    public User(){}
    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void test(){
        System.out.println("年龄是:" + this.age + "姓名是:" + this.name);
    }
}

上面是一个很基础的类,但是如果User类不是我们自己定义的,我们在外部无法看到里面有什么内容,需要引入反射机制

在java中所有东西都是对象,而User()和Student()又是Class的实例对象,得到class

public class Test {
    public static void main(String[] args){
        User user = new User();
        //通过类名
        Class c1 = User.class;
        System.out.println(c1);
        //通过对象
        Class c2 = user.getClass();
        System.out.println(c2);
        //借用forName
        try{
            Class c3 = Class.forName("User");
            System.out.println(c3);
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

上面的c1,c2,c3都是Class类的实例,代表的也都是User类,不仅是自定义的类,谁只是基本的基础数据类型都可以使用Class,比如

Class c1 = int.class;
Class c2 = string.class;
Class c3 = double.class;
Class c4 = void.class;

总结为获取Class的方法就是以下三种方法

  1. 对象名.getClass 通过对象名获取 比如上面的user.getClass
  2. 类名.class 通过类名获取 比如上面的User.class
  3. Class.forName 通过路径

获取类的方法

import java.lang.reflect.Method;

public class Print {
    public static void printClassMethodMessage(Object obj){
        //获取类的类类型
        Class c = obj.getClass();
        //获取类的名称
        System.out.println("类的名称是:" + c.getName());
        //获取方法信息
        Method[] ms = c.getMethods();
        for(int i = 0 ; i < ms.length ; i++){
            //得到方法的返回值类型的类类型
            Class returnType = ms[i].getReturnType();
            System.out.println(returnType.getName() + " ");
            //得到方法的名称
            System.out.println(ms[i].getName()+"(");
            //获取方法参数类型->得到的是参数列表的类型的类类型
            Class[] ParamTypes = ms[i].getParameterTypes();
            for(Class class1 : ParamTypes){
                System.out.println(class1.getName() + ",");
            }
            System.out.println(")");
        }
    }
}

然后传一下User

public class Test {
    public static void main(String[] args){
        User user = new User("18",20);
        Print.printClassMethodMessage(user);
    }
}

image-20210414195123214

反射获取类的方法

  1. getMethod(String name) 返回一个Method对象,name是指定的方法名,
  2. getMethods() 获取所有public函数 包括父类继承,返回Method[]数组
  3. getDeclaredMethods() 获取所有该类自己声明的方法,无论任何访问权限
  4. getDeclaredMethod(String name)返回一个Method对象,指定对应的声明方法

获取类的所有属性

    public static void printFieldMessage(Object obj){
        Class c = obj.getClass();
        //Field类封装了关于成员变量的相关操作
        //getFields()获取的是所有public的成员变量
        //getDeclaredFields()获取的是此类自己声明的成员变量的信息 无论私有还是公有
        //Field[] = c.getFields();
        Field[] fs = c.getDeclaredFields();
        for(Field field: fs){
            // 1. 获取字段类型
            Class fieldType = field.getType();
            String typename = fieldType.getName();
            // 2. 获取字段名称
            String fieldname = field.getName();
            // 3. 打印字段类型和字段名称
            System.out.println(typename+" "+fieldname);
        }
    }

image-20210414195843511

获取指定属性

    public static Object printFieldMsgBySelf(Object obj){
        Class c = obj.getClass();
        try{
            // 获取指定字段的内容
            Field age_field = c.getDeclaredField("age");
            // new实例化一个User类
            Object object = c.newInstance();
            // 使用反射机制打破封装
            age_field.setAccessible(true);
            // 为我们实例化的对象重新设置年龄
            age_field.set(object,100);
            return object;
        } catch (Exception e){
            e.printStackTrace();
        }
        return c;
    }

image-20210414201941254

在User里面添加了getAge函数,然后可以发现我们成功修改user的信息

  1. getField(String name) 返回一个名字是name的Field对象,但是要求是public
  2. getFields() 获取所有puclic的成员变量的信息
  3. getDeclaredField(String name) 获取自己声明的指定的成员变量name

获取类的构造方法

    public static void printConMessage(Object obj){
        Class c = obj.getClass();
        //Constructor封装构造函数
        // getConstructors获取所有的public的构造函数
        // getDeclaredConstructors得到所有的构造函数
        // 获取构造函数
        Constructor[] cs = c.getDeclaredConstructors();
        for(Constructor constructor : cs){
            // 获取构造函数的名字
            System.out.println(constructor.getName() + "(");
            // 获取构造函数的参数列表
            Class[] paramTypes = constructor.getParameterTypes();
            for(Class c1 : paramTypes){
                System.out.println(c1.getName()+",");
            }
            System.out.println(")");
        }
    }

image-20210414202630524

  1. getConstructor() 返回一个Constructor公共构造方法对象

  2. getConstructors() 返回所有构造方法

  3. getDeclaredConstructor() 返回一个Constructor对象,该对象反映此Class对象所表示的类或接口的指定构造方法

  4. getDeclaredConstructors() 返回一个Constructor数组,反应此类声明的所有构造方法,包括所有类型

借助反射机制了解泛型,泛型是防止错误输入的,只是在编译阶段有效,只要绕过编译就无效了,比如下面ArrayList l1 = new ArrayList(); ArrayList<String> l2 = new ArrayList<String>();l2需要输入string类型的,而如果我们getclass,然后会发现运行期间c1和c2是一致的,又因为泛型失败,可以向list添加任意对象

posted @ 2021-04-16 16:18  buchiyexiao  阅读(75)  评论(0)    收藏  举报
Live2D