java入门基础(十二)


一、类加载

  • 概述:当程序要使用某个类时,如果该类还没有加载到内存中,系统会通过类的加载,类的连接,类的初始化三个步骤来对类进行初始化。
  • 类的加载:
    将class文件(源文件)读取内存,并创建对应的Class对象
    任何类被使用时,系统都会创建一个java.lang.Class对象
  • 注意事项:初始化
    1.当类还未被加载和连接时,程序先加载并连接该类
    2.该类的直接父类未被初始化,先初始化直接父类
    3.假如类中有初始化语句(非static修饰),依次执行初始化语句
    执行步骤2时,同样遵循1-3

如果不创建对象,就想使用该对象的方法和变量,就需要通过反射使用Class类去获取。

1.反射

  • 反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。
  • 通过反射使用一个类,需要获取该类字节码文件,也就是类型为Class的对象

2.获取Class对象

  • 获取方式
    1.使用该类的class属性来获取对应的Class对象,
    2.调用该类的getClass()方法,返回该对象所属类对用的Class对象
    该方法是Object中的方法,所有类都可以调动
    3.使用Class中的静态方法forName(String className),该方法需要传入String参数,参数是某个类完整的包名
public class Test {
    public static void main(String[] args)throws Exception {
        //获取对应User的Class对象,之后可以通过Class获取类中的属性方法,无需创建新的对象
        //方法一
        User u=new User();
        Class user1=u.getClass();//Class<? extends User> user1=u.getClass()这样写也行
        System.out.println(user1);
        //方法二
        Class user2=User.class;
        System.out.println(user2);
        //方法三
        Class user3=Class.forName("reflect.User");
        System.out.println(user3);

    }
}

在这里插入图片描述

3.反射获取构造方法

  • Class类中用与获取构造的方法

  • Constructor<?>[] getConstructors():获取所有公共构造对象的数组

  • Constructor<?>[] getDeclaredConstructors():获取所有构造对象的数组

  • Constructor getConstructors(Class<?>… parameterTypes):返回单个公共构造方法对象

  • Constructor getDeclaredConstructor(Class<?>… parameterTypes):返回单个构造方法对象

创建一个类

public class User {
    private int age;
    private String name;
    private String school;
    public int grade;

    public User(){}
//注意:对于类而言,构造方法中同一类型的参数组合的构造方法只能有一个,
// 如果有多个类型相同,创建对象时,不知道是哪一个
    private User(String name) {
        this.name = name;
    }


    public User(int age){
        this.age=age;
    }


    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    private User(String name, String school) {
        this.name = name;
        this.school = school;
    }

    public User(int age, String name, String school) {
        this.age = age;
        this.name = name;
        this.school = school;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

获取该类的构造方法

package reflect;
import java.lang.reflect.Constructor;
public class Test2 {
    public static void main(String[] args) throws Exception {
        Class user=User.class;
        
        //获取所有公共构造对象的数组
        Constructor[] constructors1=user.getConstructors();
        for(Constructor c1:constructors1){
            System.out.println(c1);
        }
        System.out.println("===============");
        
        //获取所有构造对象的数组
        Constructor[] constructors2=user.getDeclaredConstructors();
        for(Constructor c2:constructors2){
            System.out.println(c2);
        }
        System.out.println("===========");
        
        //获取公共构造方法的对象,只能返回公共的,返回私有构造运行时会报错
        Constructor constructors3=user.getConstructor(int.class);
        Constructor constructor4=user.getConstructor(int.class,String.class);
        System.out.println(constructors3);
        System.out.println(constructor4);
        System.out.println("=====================");
        
        //获取公共构造方法的对象,可以返回公有的和私有的
        Constructor constructor5=user.getDeclaredConstructor(String.class);
        Constructor constructor6=user.getDeclaredConstructor(int.class);
        System.out.println(constructor5);
        System.out.println(constructor6);
        
    }
}

在这里插入图片描述

4.构造方法创建对象

  • T newInstance(Object… initargs);根据指定的构造方法创建对象
    注意:通过反射私有化构造不能直接创建对象需要通过setAccessible方法

package reflect;

public class User {
    private int age;
    private String name;
    private String school;
    public int grade;

    public User(){}
//注意:对于类而言,构造方法中同一类型的参数组合的构造方法只能有一个,
// 如果有多个类型相同,创建对象时,不知道是哪一个
    private User(String name) {
        this.name = name;
    }


    public User(int age){
        this.age=age;
    }


    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    private User(String name, String school) {
        this.name = name;
        this.school = school;
    }

    public User(int age, String name, String school) {
        this.age = age;
        this.name = name;
        this.school = school;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", school='" + school + '\'' +
                '}';
    }

    public void setAge(int age) {
        this.age = age;
    }
}

创建对象

import java.lang.reflect.Constructor;

public class Test3 {
    public static void main(String[] args) throws Exception{
        Class u=User.class;//获取该类的Class对象

        Constructor constructor1=u.getConstructor(int.class);//获取该类的构造方法
        Object object1=constructor1.newInstance(23);//创建对象,这里只能用Object修饰,不能用User
        //想要获得User对象需要向下转型
        User user1=(User)object1;
        System.out.println(user1.toString());

        //私有化构造不能直接创建对象,需要通过setAccessible方法,否者运行时报错
        Constructor constructor2=u.getDeclaredConstructor(String.class);
        constructor2.setAccessible(true);//默认为false
        Object object2=constructor2.newInstance("张三");
        User user2=(User)object2;
        System.out.println(user2.toString());

    }
}

在这里插入图片描述

5.反射获取成员变量

  • Class类中用与获取成员变量的方法
  • Field[] getFields();获取所有公共成员变量的数组
  • Field[] getDeclaredFields();获取所有成员变量的数组
  • Field[] getFields(String name);返回单个公共成员变量的对象
  • Field[] getDeclaredFields(String name);返回单个成员变量的对象

直接给测试类(这里要使用的类和4构造方法创建对象的User类相同,此处不在给出)

import java.lang.reflect.Field;
public class Test4 {
    public static void main(String[] args)throws Exception {
        Class u=Class.forName("reflect.User");
        //获取所有公共成员变量
        Field[] fields1=u.getFields();
        for(Field f1:fields1){
            System.out.println(f1);
        }
        System.out.println("============");
        //获取所有成员变量,包括私有
        Field[] fields2=u.getDeclaredFields();
        for(Field f2:fields2){
            System.out.println(f2);
        }
        System.out.println("===============");
        //返回单个公有成员变量的对象,参数为变量名的字符串
        Field field1=u.getField("grade");
        System.out.println(field1);
        System.out.println("============");
        //返回单个私有或者公有成员变量的对象
        Field field2=u.getDeclaredField("name");
        System.out.println(field2);
    }
}

在这里插入图片描述

6.反射给成员变量赋值

  • Class类中用与成员变量赋值的方法
    void set(Object obj,Object value):给obj对象的成员赋值value

  • 注意:通过反射私有化成员不能直接赋值需要通过setAccessible方法

user类例:

public class User {
    private int age;
    private String name;
    private String school;
    public int grade;

    public User(){}
//注意:对于类而言,构造方法中同一类型的参数组合的构造方法只能有一个,
// 如果有多个类型相同,创建对象时,不知道是哪一个
    private User(String name) {
        this.name = name;
    }


    public User(int age){
        this.age=age;
    }


    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    private User(String name, String school) {
        this.name = name;
        this.school = school;
    }

    public User(int age, String name, String school) {
        this.age = age;
        this.name = name;
        this.school = school;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", school='" + school + '\'' +
                ", grade=" + grade +
                '}';
    }

    public void setAge(int age) {
        this.age = age;
    }
}

测试,更改变量值

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class Test5 {
    public static void main(String[] args)throws Exception {
        //用加载类获得一个对象,并初始化,grade没有赋值默认为零
        Class u=Class.forName("reflect.User");
        Constructor constructor=u.getConstructor(int.class,String.class,String.class);
        Object o=constructor.newInstance(16,"张三","北京大学");
        User user1=(User)o;
        System.out.println(user1.toString());
        //更改私有变量的值
        Field field1=u.getDeclaredField("age");
        field1.setAccessible(true);
        field1.set(user1,18);
        //更改公有变量的值
        Field field2=u.getField("grade");
        field2.set(user1,98);
        System.out.println(user1.toString());
    }
}

在这里插入图片描述

7.反射获取成员方法

  • Class类中用与获取成员方法的方法
  • Method[] getMethods();获取所有公共成员方法(包括继承)的数组
  • Method[] getDeclaredMethods();获取所有成员方法(不包括继承)的数组
  • Method getMethod(String name,Class<?>… parameterTypes);返回单个公共成员方法的对象
  • Method getDeclaredMethod(String name,Class<?>… parameterTypes);返回单个成员方法的对象

父类User

public class User {
    private int age;
    private String name;
    private String school;
    public int grade;

    public User(){}
//注意:对于类而言,构造方法中同一类型的参数组合的构造方法只能有一个,
// 如果有多个类型相同,创建对象时,不知道是哪一个
    private User(String name) {
        this.name = name;
    }


    public User(int age){
        this.age=age;
    }


    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    private User(String name, String school) {
        this.name = name;
        this.school = school;
    }

    public User(int age, String name, String school) {
        this.age = age;
        this.name = name;
        this.school = school;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", school='" + school + '\'' +
                ", grade=" + grade +
                '}';
    }

    public void setAge(int age) {
        this.age = age;
    }
}

子类继承父类

public class Child extends User {
    public void show(){
        System.out.println("我是一个子类");
    }

    private void test(){
        System.out.println("我是一个私有子类");
    }
}
import java.lang.reflect.Method;
public class Test6 {
    public static void main(String[] args) throws Exception{
        Class c=Child.class;
        //获取所有成员方法,包括私有公有,但不包括继承
        Method[] methods1=c.getDeclaredMethods();
        for(Method m1:methods1){
            System.out.println(m1);
        }
        System.out.println("=================");
        //获取所有公共成员方法,包括继承,不包括私有方法
        Method[] methods2=c.getMethods();
        for(Method m2:methods2){
            System.out.println(m2);
        }
        System.out.println("===============");
        //返回公共的方法,参数为方法名的字符串,和方法的参数类型
        //show没有参数,此处没有给出。(带参的参考第8点案例)
        Method method1=c.getMethod("show");//获取不到私有的test
        System.out.println(method1);
        System.out.println("================");
        //返回私有的方法
        Method method2=c.getDeclaredMethod("test");
        System.out.println(method2);

    }
}

在这里插入图片描述
在这里插入图片描述

8.反射使用成员方法

  • Method类中用与调用成员方法的方法
  • Object invoke(Object obj,Object…args):调用obj对象的成员方法参数为args,返回值为Object
    注意:通过反射私有化成员方法不能直接调用需要通过setAccessible方法

子类和父类参照第7点,这里直接给出测试类

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Test7 {
    public static void main(String[] args)throws Exception {
        //创建一个对象
        Class c=Child.class;
        Constructor constructor=c.getConstructor();
        Object object1=constructor.newInstance();
        Child child1=(Child)object1;
        //使用公有方法
        Method method1=c.getMethod("setSchool", String.class);
        method1.invoke(child1,"清华大学");
        Method method2=c.getMethod("getSchool");
        System.out.println(method2.invoke(child1));
        //使用私有方法,和私有变量一样私有构造一样,需调用setAccessible方法
        Method method3=c.getDeclaredMethod("test");
        method3.setAccessible(true);
        method3.invoke(child1);
    }
}

在这里插入图片描述

二、正则表达式

  • 作用:通过简单的表达式验证格式是否符合要求
    1.正则表达式符号
    在这里插入图片描述
    在这里插入图片描述
    代码演示:

案例一

import java.util.regex.Matcher;
import java.util.regex.Pattern;

//验证以1开头的电话号码的格式是否正确
public class Test1 {
    public static void main(String[] args) {
        String reg="1[0-9]{10}$";//以1开始,0-9个数字,匹配10次,以$结束
        Pattern pattern = Pattern.compile(reg);//把原本是Str的格式转化为正则表达式
        String phone1="12333458876";
        String phnoe2="23323882456";
        String phone3="1213488";
        Matcher matcher1 = pattern.matcher(phone1);//匹配数据
        Matcher matcher2 = pattern.matcher(phnoe2);
        Matcher matcher3 = pattern.matcher(phone3);
        System.out.println(matcher1.matches());
        System.out.println(matcher2.matches());
        System.out.println(matcher3.matches());
    }
}

在这里插入图片描述

案例二:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

//验证qq邮箱是否正确:格式 QQ号  @  qq.com
public class Test2 {
    public static void main(String[] args) {
        String reg="^[0-9]+@qq.com$";
        Pattern pattern=Pattern.compile(reg);

        String s1="234324@qq.com";
        String s2="ssf556@qq.com";
        String s3="13345855@qq.com.cn";
        Matcher matcher;
        matcher=pattern.matcher(s1);
        System.out.println(matcher.matches());
        matcher=pattern.matcher(s2);
        System.out.println(matcher.matches());
        matcher=pattern.matcher(s3);
        System.out.println(matcher.matches());
    }
}

在这里插入图片描述

三、总结

反射:在运行状态中,获取任意一个类(编译状态的类)的属性方法构造
	类加载:
		1.类的加载:把后缀为.class的源文件加载到内存中并生成对应的Class对象
		2.类的连接:类的检测,检测类是否合法
			验证阶段:检验被加载的类和相关类(父类/接口)内部结构是否合法
			准备阶段:负责为类中的变量分配内存,并设置默认值
			解析阶段:将类的二进制数据中字符(方法)引用改为直接引用
		3.类的初始化:赋值
	获取Class对象的方式:
		1.类名.class
		2.类对象.getClass()
		3.Class.forName(类的相对路径,相对于src);
	获取构造:
		Constructor<?>[] getConstructors():获取所有公共构造对象的数组
		Constructor<?>[] getDeclaredConstructors():获取所有构造对象的数组
		Constructor[] getConstructors(Class<?>... parameterTypes):返回单个公共构造方法对象
		Constructor[] getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
	使用构造:
		T newInstance(Object... initargs);根据指定的构造方法创建对象
	注意:Class中有newInstance(),只能使用无参构造
		 Constructor中有newInstance(Object... initargs),根据获取的构造来指定参数创建对象
		通过反射私有化构造不能直接创建对象需要通过setAccessible(true)方法,绕过检测机制
	获取变量:
		Field[] getFields();获取所有公共成员变量的数组
		Field[] getDeclaredFields();获取所有成员变量的数组
		Field[] getFields(String name);返回单个公共成员变量的对象
		Field[] getDeclaredFields(String name);返回单个成员变量的对象
    赋值:
    	void set(Object obj,Object value):给obj对象的成员赋值value
    注意:通过反射私有化边浪不能直接赋值需要通过setAccessible(true)方法,绕过检测机制
    获取方法:
    	Method[] getMethods();获取所有公共成员方法(包括继承)的数组
		Method[] getDeclaredMethods();获取所有成员方法(不包括继承)的数组
		Method[] getMethods(String name,Class<?>... parameterTypes);返回单个公共成员方法的对象
		Method[] getDeclaredMethods(String name,Class<?>... parameterTypes);返回单个成员方法的对象
	使用方法:
		Object invoke(Object obj,Object...args):调用obj对象的成员方法参数为args,返回值为Object
	注意:通过反射私有化成员方法不能直接调用需要通过setAccessible方法
正则表达式:
	符号
		/…/	代表一个模式的开始和结束
		^	匹配字符串的开始
		$	匹配字符串的结束
		\s	任何空白字符
		\S	任何非空白字符
		\d	匹配一个数字字符,等价于[0-9]
		\D	除了数字之外的任何字符,等价于[^0-9]
		\w	匹配一个数字、下划线或字母字符,等价于[A-Za-z0-9_]
		\W	任何非单字字符,等价于[^a-zA-z0-9_]
		.	除了换行符之外的任意字符
		{n}	匹配前一项n次
		{n,}	匹配前一项n次,或者多次
		{n,m}	匹配前一项至少n次,但是不能超过m次
		*	匹配前一项0次或多次,等价于{0,}
		+	匹配前一项1次或多次,等价于{1,}
		?	匹配前一项0次或1次,也就是说前一项是可选的,等价于{0,1}

		例子判断手机号:
			String reg="^1[0-9]{10}$"
			String str="10234567852"
			//1.把自定义的格式识别为正则表达式
			Pattern pattern = Pattern.compile(reg);
			//2.匹配数据
        	Matcher matcher = pattern.matcher(email);
        	//3.获取结果
        	System.out.println(matcher.matches());

java入门基础学习(一)
java入门基础学习(二)
java入门基础学习(三)
java入门基础学习(四)
java入门基础学习(五)
java入门基础学习(六)
java入门基础学习(七)
java入门基础学习(八)
java入门基础学习(九)
java入门基础学习(十)
java入门基础学习(十一)
java进阶之常见对象(一)
java进阶之常见对象(二)
java进阶之冒泡排序
java进阶之选择排序
java进阶之面向对象(封装)
java进阶之面向对象(代码块、继承)
java进阶之面向对象(多态、抽象、接口)
java进阶之匿名内部类、访问修饰符、包

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值