【小白学java】D34》》》类加载(器)& 反射 & 正则表达式

《【小白学java】D34》》》类加载(器)& 反射 & 正则表达式》

🧡🤎感谢各位一直以来的支持和鼓励🧡🤎
制作不易求点赞 收藏 ⭐ ⭐ ⭐ 关注
▛▛▛▛▛▛▛▛▛▛▛▛▛▛▛▛▛▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜▜
🧡🤎 一键三连走起 🧡🤎

一、 了解类加载

(1 )概述:

        当程序要使用某个类时,如果该类还没有加载到内存中,系统会通过类的加载,类的连接,类的初始化三个步骤来对类进行初始化

(2)类的加载

  • 将class文件(源文件)读取内存,并创建对应的Class对象
  • 任何类被使用时,系统都会创建一个java.lang.Class对象

(3) 类的连接

  • 验证阶段:检验被加载的类和相关类(父类/接口)内部结构是否合法
  • 准备阶段:负责为类中的变量分配内存,并设置默认值
  • 解析阶段:将类的二进制数据中字符(方法)引用改为直接引用

(4)类的初始化:

        对类变量进行初始化(赋值)

  • 1.当类还未被加载和连接时,程序要先加载并连接该类
  • 2.该类的直接父类未被初始化,要先初始化直接父类
  • 3.假如类中有初始化语句(非static修饰),那么依次执行初始化语句
    执行步骤2时,同样遵循1-3

(5)类加载的使用

  • 创建类的实例
  • 操作类或相关的类变量
  • 调用类方法
  • 初始化子类
  • 直接使用java.exe运行某个主类
  • 使用反射方式强制创建类或接口对应的Class对象

二、类加载器

        Java加载类时,都是通过类加载器来进行加载

(1)类加载器的作用:

        负责将class文件加载到内存中,生成对应的Class对象

(2)类加载器的机制

  • 全盘负责:当类加载器负责加载某一个class文件时,与之相关的class文件也由该类加载器负责,除非显示由另一个加载器负责
  • 父类委托:加载某一个class文件时,先让父类的加载器试图加载该class文件,只有在父类无法加载该class文件时,才尝试从自己的类路径加载
  • 缓存机制:会把所有加载的class文件生成的Class对象进行缓存,当程序需要使用某一个Class对象时,类加载器首先去缓存中搜索,缓存中不存在时,才会将class文件加载到内存中,并生成对应的Class对象

三、反射

        反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。这也就是Java被视为动态(或准动态)原因,为什么说是准动态,是因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。

(1) 反射获取Class对象

通过反射使用一个类,需要获取该类字节码文件,也就是类型为Class的对象

获取方式

  • 1.使用该类的class属性来获取对应的Class对象,
  • 2.调用该类的getClass()方法,返回该对象所属类对用的Class对象
    该方法是Object中的方法,所有类都可以调动
  • 3.使用Class中的静态方法forName(String className),该方法需要传入String参数,参数是某个类完整的包名

示例代码:

//1.使用该类的class属性来获取对应的Class对象,
// 获取User类编译后的字节码文件 User.class
Class<User> userClass = User.class;
System.out.println(userClass);
//class com.xiaobei.lambda.demo_class.User 返回该类的路径(位置)

//2.调用getClass()方法,返回该对象所属类对用的Class对象
// getClass()方法是Object中的方法,所有类都可以调动,
User user = new User();//创建对象
Class<? extends User> userClass1 = user.getClass();
System.out.println(userClass1);
//class com.xiaobei.lambda.demo_class.User 返回该类的路径(位置)

// 3.使用Class中的静态方法forName(String className),
// 该方法需要传入String类型的参数,参数是某个类完整的包名
Class<?> aClass = Class.forName("com.xiaobei.lambda.demo_class.User");
System.out.println(aClass);

测试结果:
《【小白学java】D34》》》类加载(器)& 反射 & 正则表达式》

(2)反射获取构造方法

Class类中用于获取构造方法的方法:

Constructor<?>[] getConstructors():
			获取所有公共构造对象的数组
Constructor<?>[] getDeclaredConstructors():
			获取所有构造对象的数组
Constructor<T>[] getConstructors(Class<?>... parameterTypes):
			返回单个公共构造方法对象
Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):
			返回单个构造方法对象

Class类中用于使用构造方法的方法:

T newInstance(Object... initargs);
			根据指定的构造方法创建对象

注意:
通过反射私有化构造不能直接创建对象需要通过setAccessible方法

示例代码;

public class User { 
    
    //无参构造
    public User() { 
    System.out.println("我是无参构造");
    }

    //有参构造
    public User(String name) { 
        System.out.println("我是有参构造\t"+name);

    }
    //私有构造
    private  User(String name,int age){ 
        System.out.println("我是私有有参构造\t"+name+"--"+age);
    }

}
public class Test { 
    public static void main(String[] args) throws NoSuchMethodException { 
        // 获取User类编译后的字节码文件 User.class
        Class<User> userClass = User.class;
        //1. Constructor<?>[] getConstructors():获取所有公共构造对象的数组
        System.out.println("获取所有公共构造对象的数组");
        Constructor<?>[] userClassConstructors = userClass.getConstructors();
        for (Constructor<?> userClassConstructor : userClassConstructors) { 
            System.out.println(userClassConstructor);
        }
        System.out.println("--------------------------------");

        //2.Constructor<?>[] getDeclaredConstructors():获取所有构造对象的数组
        System.out.println("获取所有构造对象的数组");
        Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) { 
            System.out.println(declaredConstructor);
        }
        System.out.println("--------------------------------");

        //3. Constructor<T>[] getConstructors(Class<?>... parameterTypes):返回单个公共构造方法对象
        System.out.println("返回单个公共构造方法对象");
        Constructor<User> constructor = userClass.getConstructor(String.class);
        System.out.println(constructor);
        System.out.println("--------------------------------");

        //4. Constructor<T>[] getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
        System.out.println("返回单个构造方法对象");
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class,int.class);
        System.out.println(declaredConstructor);
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor1);
        System.out.println("--------------------------------");
         

 //5. T newInstance(Object... initargs);根据指定的构造方法创建对象
        //每个类都有一个默认的构造方法,所以不需要指定,可以直接使用
        User user = userClass.newInstance();
        System.out.println(user);
        //使用指定构造方法创建对象
        Constructor<User> declaredConstructor2 = userClass.getDeclaredConstructor(String.class);
        User user1 = declaredConstructor2.newInstance("张三");
        System.out.println(user1);
        //使用指定私有方法创建对象
        //注意:会报错private 修饰的无妨创建
        //解决办法:因为编译过程中会检测是否符合Java语法格式,那么我们可以绕过编译安全检测机制(又称“暴力反射”/“暴射”)
        Constructor<User> declaredConstructor3 = userClass.getDeclaredConstructor(String.class, int.class);
        //设置为可通行的语法格式,可以让Class对象认为private修饰的构造符合
        declaredConstructor3.setAccessible(true);
        User user2 = declaredConstructor3.newInstance("李四", 20);
        System.out.println(user2);



    }
}

测试结果:
《【小白学java】D34》》》类加载(器)& 反射 & 正则表达式》

(3)反射获取成员变量方法

Class类中用与获取成员变量的方法

Field[] getFields();获取所有公共成员变量的数组
Field[] getDeclaredFields();获取所有成员变量的数组
Field[] getFields(String name);返回单个公共成员变量的对象
Field[] getDeclaredFields(String name);返回单个成员变量的对象

Class类中用与成员变量赋值的方法

void set(Object obj,Object value): 给obj对象的成员赋值value

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

示例代码:

public class User { 
    public String name;
    public int  uid;

    private int age;
    private  double weight;
}
public class Test { 
    public static void main(String[] args) throws Exception { 
        // 获取User类编译后的字节码文件 User.class
        Class<User> userClass = User.class;
        //Class类中用与获取成员变量的方法
        //Field[] getFields();获取所有公共成员变量的数组
        System.out.println("获取所有公共成员变量的数组");
        Field[] fields = userClass.getFields();
        for (Field field : fields) { 
            System.out.println(field);
        }
        System.out.println("-----------------------------");

        //Field[] getDeclaredFields();获取所有成员变量的数组
        System.out.println("获取所有成员变量的数组");
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) { 
            System.out.println(declaredField);
        }
        System.out.println("-----------------------------");

        //Field[] getFields(String name);返回单个公共成员变量的对象
        System.out.println("返回单个公共成员变量的对象");
        Field field = userClass.getField("name");
        System.out.println(field);
        System.out.println("-----------------------------");

        //Field[] getDeclaredFields(String name);返回单个成员变量的对象
        System.out.println("返回单个成员变量的对象");
        Field name = userClass.getDeclaredField("name");
        System.out.println(name);
        Field age = userClass.getDeclaredField("age");
        System.out.println(age);
        System.out.println("-----------------------------");

        //Class类中用与成员变量赋值的方法
        //void set(Object obj,Object value):给obj对象的成员赋值value
        //给公有的成员变量赋值
        System.out.println("给公有的成员变量赋值");
        Field name1 = userClass.getDeclaredField("name");
        User user = userClass.newInstance();
        name1.set(user,"张三");
        System.out.println(user.name);
        //给私有的成员变量赋值
        System.out.println("给私有的成员变量赋值");
        Field age1 = userClass.getDeclaredField("age");
        //绕过安全检测机制
        age1.setAccessible(true);
        User user1 = userClass.newInstance();
        age1.set(user1,20);
        //System.out.println(user1.age);//不符合java语法
        Object o = age1.get(user1);
        System.out.println(o);
    }
}

测试结果:

《【小白学java】D34》》》类加载(器)& 反射 & 正则表达式》

(4)反射获取成员方法方法

Class类中用与获取成员变量的方法

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

Method类中用与调用成员方法的方法

Object invoke(Object obj,Object...args):
		调用obj对象的成员方法参数为args,返回值为Object

注意:
	通过反射私有化成员方法不能直接调用,需要通过setAccessible方法

测试代码:

public class User { 

    public void  fun(){ 
        System.out.println("我是公有无参成员方法");
    }
    public void  show(int sum){ 
        System.out.println("我是公有有参成员方法"+ sum);
    }

    private void  fun1(){ 
        System.out.println("我是私有无参成员方法");
    }
    private void  show1(int sum){ 
        System.out.println("我是私有有参成员方法"+ sum);
    }

}

public class Test { 
    public static void main(String[] args) throws Exception { 
        // 获取User类编译后的字节码文件 User.class
        Class<User> userClass = User.class;

        //Class类中用与获取成员变量的方法
        //Method[] getMethods();获取所有公共成员方法(包括继承)的数组
        System.out.println("获取所有公共成员方法(包括继承)的数组");
        Method[] methods = userClass.getMethods();
        for (Method method : methods) { 
            System.out.println(method);
        }
        System.out.println("----------------------------------");

        //Method[] getDeclaredMethods();获取所有成员方法(不包括继承)的数组
        System.out.println("获取所有成员方法(不包括继承)的数组");
        Method[] declaredMethods = userClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) { 
            System.out.println(declaredMethod);
        }
        System.out.println("----------------------------------");

        //Method[] getMethod(String name,Class<?>... parameterTypes);返回单个公共成员方法的对象
        System.out.println("返回单个公共成员方法的对象");
        Method show = userClass.getMethod("fun");
        System.out.println(show);
        System.out.println("----------------------------------");

        //Method[] getDeclaredMethods(String name,Class<?>... parameterTypes);返回单个成员方法的对象
        System.out.println("返回单个成员方法的对象");
        //公有
        Method show1 = userClass.getDeclaredMethod("show", int.class);
        System.out.println(show1);
        //私有
        Method show11 = userClass.getDeclaredMethod("show1", int.class);
        System.out.println(show11);
        System.out.println("----------------------------------");


        //Method类中用与调用成员方法的方法
        //Object invoke(Object obj,Object...args):
        // 调用obj对象的成员方法参数为args,返回值为Object
        //公有
        Method show12 = userClass.getDeclaredMethod("fun");
        User user = userClass.newInstance();
        show12.invoke(user);
        //私有
        Method show13 = userClass.getDeclaredMethod("show1", int.class);
        show13.setAccessible(true);//绕过类型检测机制
        User user1 = userClass.newInstance();
        show13.invoke(user1,30);

    }
}

测试结果:
《【小白学java】D34》》》类加载(器)& 反射 & 正则表达式》《【小白学java】D34》》》类加载(器)& 反射 & 正则表达式》

四、正则表达式

正则表达式的作用

        使用简洁的代码,严谨的验证文本框中的内容

正则表达式的模式

  • 简单模式:只能表示具体的匹配
  • 复合模式:可以使用通配符表达更为抽象的规则模式

正则表达式符号

符号功能描述
匹配的内容
/…/表示一个模式的开始和结束
^表示匹配字符串的开始
$表示匹配字符串的结束
\s表示任何的空白字符
\S表示任何的非空白字符
\d表示匹配一个数字字符,等价于[0-9]
\D表示除了数字之外的任何字符,等价于[^0-9]
\w表示匹配一个数字、下划线或字母字符,等价于[A-Za-z0-9_ ]
\W表示任何非单字字符,等价于[^a-zA-z0-9_ ]
.表示除了换行符之外的任意字符
[a-z]表示匹配a到z之间的任意字符
匹配的次数
{n}表示匹配前一项n次
{n,}表示匹配前一项n次,或者多次
{n,m}表示匹配前一项至少n次,但是不能超过m次
*表示 匹配前一项0次或多次,等价于{0,}
+表示匹配前一项1次或多次,等价于{1,}
表示匹配前一项0次或1次,也就是说前一项是可选的,等价于{0,1}

正则表达式的功能

	匹配:	matches
	切割:	split
	替换:	replaceAll
	获取:	find、group

正则表达式的使用

【案例一】:判断QQ号是否合法

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

public class Task { 
    public static void main(String[] args) { 
        //判断QQ号(5-10位)是否合法,例如:12345678(5-8位数字)
        String  qq="2601149032";
        //写正则表达式
        String reg="^[1-9]{5,9}$";
        //转换String->Reg
        //使用Pattern类compile()方法
        Pattern compile = Pattern.compile(reg);
        //匹配,调用Matcher类的matcher()方法,匹配判断是否合法
        Matcher matcher = compile.matcher(qq);
        //调用find()方法,判断匹配是否合法
        boolean b = matcher.find();
        System.out.println(b);//返回true,合法
    }
}

【案例二】:判断手机号是否合法

public class Task { 
    public static void main(String[] args) { 
		//判断手机号(1开头,11位数)是否合法
        String  qq="13850536081";
        //写正则表达式
        String reg="^1[0-9]{10}$";
        //转换String->Reg
        //使用Pattern类compile()方法
        Pattern compile = Pattern.compile(reg);
        //匹配,调用Matcher类的matcher()方法,匹配判断是否合法
        Matcher matcher = compile.matcher(qq);
        //调用find()方法,判断匹配是否合法
        boolean b = matcher.find();
        System.out.println(b);//true,合法
   }
}

【案例三】:判断QQEmail是否合法

public class Task { 
    public static void main(String[] args) { 
		//验证QQ邮箱是否合法(0不能开头,6-10位数字,后缀 @qq.com)
        String qqemail="123ab67891@qq.com";
        String reg ="^[1-9][0-9]{5,9}@qq.com$";
        Pattern compile = Pattern.compile(reg);
        Matcher matcher = compile.matcher(qqemail);
        boolean b = matcher.find();
        System.out.println(b);//返回false,不合法
   }
}

【案例四】:判断邮箱的格式是否正确

以123ab67891@qq.com和a1236548@163.com为例演示

public class Task { 
    public static void main(String[] args) { 
		//验证邮箱格式是否合法(10位数字,后缀 @qq.com或则@163.com)
        //QQ邮箱,(0不能开头,6-10位数字,后缀 @qq.com)
        String qqemail="123ab67891@qq.com";
        //网易邮箱,允许有一个字母5-11个数字@163.com
        String wyemail="a1236548@163.com";

        //String reg ="^(([1-9][0-9]{5,9}@qq.com)|([A-z][0-9]{5,11}@163.com))$";
        String reg ="^([1-9][0-9]{5,9}@qq)|([A-z][0-9]{5,11}@163).com$";
        Pattern compile = Pattern.compile(reg);

        Matcher matcher = compile.matcher(qqemail);
        boolean b = matcher.find();
        System.out.println(b);//返回false,不合法

        Matcher matcher1 = compile.matcher(wyemail);
        boolean b1 = matcher1.find();
        System.out.println(b1);//返回true,合法
   }
}
    原文作者:北慕辰
    原文地址: https://blog.csdn.net/dazuo_001/article/details/119242363
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞