1、资源绑定器
资源绑定器,便于获取属性配置文件中的内容
使用一下这种方式的时候,属性配置文件xxx.properties必须放在类路径下
ResourceBundle bundle=ResourceBundle.getBundle("类路径下的文件名")
//再写路径的时候。路径后面的扩展名不能写(tempfile03中写了user=username) ResourceBundle bundle =ResourceBundle.getBundle("tempfile03"); String name=bundle.getString("user"); System.out.println(name);//username
2、类加载器(了解)
1>、什么是类加载器?
专门负责加载类的命令/工具
2>、类加载器的种类
启动类加载器,扩展类加载器,应用类加载器
3>、假设有这样一段代码
String s="asd";
代码在开始执行之前,会将所需要的类全部加载到JVM中。通过类加载器加载,看到以上代码类加载器会找String.class文件,找到就加载,那么是怎样加载的呢?
a、首先通过"启动类加载器"加载。
注意:启动类加载器专门加载jre下的rt.jar,jdk11以后都找不到jre文件了,rt.jar中都是JDK最核心的类库。
b、如果通过启动类加载器加载不到,就会用扩展类加载器加载jre下lib中的ext
c、如果扩展类加载器加载不到,则会通过应用类加载器,会专门加载classpath中的jar包(class文件)
4>、java为了保证类加载安全,使用了双亲委派机制,优先从启动类加载器加载,成为”父“,”父“无法加载到,再从扩展类加载器加载,称”母“,双亲委派,如果都加载不到,才会考虑从应用类加载器中加载,直到加载到为止。
3、使用反射机制获取Field
public static void main(String[] args) { try { //获取属性之前,需要获取类 Class cname = Class.forName("TwentyFiveDay.StudentClass"); //获取类名 String name = cname.getName(); System.out.println(name);//TwentyFiveDay.StudentClass //获取简易类名 String sname=cname.getSimpleName(); System.out.println(sname);//StudentClass //获得类的属性名 Field[] fields = cname.getDeclaredFields(); //测一下fields的长度 System.out.println(fields.length);//4 for (Field field : fields) { //遍历输出类属性的修饰符 field.getModifiers()返回的是整型数字,代表的是修饰符的编号 int i=field.getModifiers(); //Modifier.toString(int i)方法把修饰符编号转换成对应的修饰符 String modifier= Modifier.toString(i); System.out.println(modifier); //遍历输出类属性的类型 field.getType()返回的是class类型的 System.out.println(field.getType().getSimpleName()+" "); //遍历输出类的属性名 System.out.println(field.getName()+" ");//sno sname sclass age } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
4、使用反射机制给属性赋值,获取属性的值
public static void main(String[] args) throws Exception{ //使用new对象的方式 StudentClass studentClass=new StudentClass(); studentClass.age=12; System.out.println(studentClass.age); //使用反射机制获取对象,并给对象的属性赋值 //第一步获取StudentClass类 Class student=Class.forName("TwentyFiveDay.StudentClass"); //第二步给类创建一个对象 Object stu=student.newInstance();//底层调用无参构造方法创建对象 //第三步获取stu对象的其中一个公有属性 Field sno = student.getDeclaredField("sno"); //给sno赋值 .set(对象,值)方法 sno.set(stu,123); //获取stu属性sno的值 Object o = sno.get(stu); System.out.println(o); //获取私有属性 Field sname = student.getDeclaredField("sname"); //私有属性的获取必须打破封装 这个是反射机制的缺点,打破封装外部也可以访问,不安全 sname.setAccessible(true); //赋值 sname.set(stu,"jack"); //获取 System.out.println(sname.get(stu)); }
5、通过反射机制调用方法
public static void main(String[] args) throws Exception{ //new对象来调用方法 userServiceClass user=new userServiceClass(); boolean result=user.UserRegister("adim","123"); System.out.println(result?"登录成功":"登陆失败");//登录成功 //使用反射机制来调用方法 //第一步获取userServiceClass类 Class userService=Class.forName("TwentyFiveDay.userServiceClass"); //第二步创建对象 Object users=userService.newInstance(); //第三步获取方法 Method Register=userService.getDeclaredMethod("UserRegister", String.class, String.class); //第四步调用方法 Object o = Register.invoke(users, "adim", "123"); System.out.println(o);//true }
6、通过反射机制实例化对象
public static void main(String[] args) throws Exception{ //new对象来调用有参构造方法 AnimalClass animalClass=new AnimalClass(); AnimalClass animalClass1=new AnimalClass(001,"erha",2); System.out.println(animalClass1);//AnimalClass{no=1, name='erha', age=2} //通过反射机制来调用有参构造方法 //第一步获取AnimalClass类 Class animal=Class.forName("TwentyFiveDay.AnimalClass"); //第二步调用无参构造创建对象 Object animalObj=animal.newInstance(); //调用有参构造的步骤一:获取有参构造方法名 Constructor constructor = animal.getDeclaredConstructor(int.class, String.class, int.class); //第二步:创建对象 Object bosi = constructor.newInstance(01, "bosi", 2); System.out.println(bosi);//AnimalClass{no=1, name='bosi', age=2} }
7、通过反射机制获取父类及接口
public static void main(String[] args) throws Exception{ //第一步获取这个类 Class string=Class.forName("java.lang.String"); //第二步获取父类 Class superclass = string.getSuperclass(); System.out.println(superclass.getName()); //第三步获取接口数组 Class[] interfaces=string.getInterfaces(); for (Class anInterface : interfaces) { System.out.println(anInterface.getName()); } }
8、注解
注解:又叫做注释,英文单词是:Annotation,它是引用类型,会编译为.class文件
注解可以出现在任何地方,注解上,方法上,类上,变量上,枚举,接口....
注解格式:修饰符 @interface 注解名{}
**需要掌握的Java.lang包下的注解:
@Deprecated的程序元素是程序员不鼓励使用的程序元素,通常是因为它是危险的,或者因为存在更好的替代方法。作用:表示被标注的东西已过时
@Override 表示方法声明旨在覆盖超类型中的方法声明,@Override:只能注解方法,这个注解是给编译器参考的,和运行阶段没有关系,凡是有这个注解,编译器都会进行检查,如果这个方法不是重写父类的方法,编译器报错。
**元注解:用来标注注解类型的注解
常用元注解:Target Retention
关于Target:用来标注”被标注的注解“只能出现在什么位置
@Target(ElementType.METHOD) :表示被标注的注解只能出现在方法上
关于Retention:用来标注”被标注的注解“最终保存在哪里
@Retention(RetentionPolicy.SOURCE):表示被标注的注解最终保存在java源文件中
@Retention(RetentionPolicy.CLASS):表示被标注的注解保存在class文件中
@Retention(RetentionPolicy.RUNTIME):表示被标注的注解保存在class文件中,并且可以让反射机制读取到
9、自定义注解
//自定义注解MyAnnotation
public @interface MyAnnotation { //注解里可以写属性,看着像方法,我们称之为属性 String name(); //可以给属性赋默认值 这样在给其他方法或类注释的时候可不写 int age() default 1; }
//自定义注解MyAnnotation01
注解里的属性类型都可以有哪些 可以是:byte,short,int,long,float,double,boolean,char,String,Class,enum类型及它们的数组形式
public @interface MyAnnotation01 { Weather[] value(); }
//enum枚举
public enum Weather { SNOW,SUN,RAIN,CLOUDY }
//自定义注解MyAnnotation02
使用元注解,标注 MyAnnotation02注解只能标注类与方法
@Target({ElementType.METHOD,ElementType.TYPE})//省略了value,只允许该注解标注方法与类 @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation02 { String[] value(); }
//测试注解类AnnotationTest01
//自定义的注解,里面可以有属性,但是若不是default了值,就需要写出来如name属性,age已经设置了默认值可不写 @MyAnnotation(name="自定义注解",age=2) public class AnnotationTest01 { //@Override public String toString() { return "AnnotationTest01{}"; } //@Deprecated//表示已过时 public static void method(){ } }
//测试注解类A
class A{ //注解里只有value一个属性,可以省略”value=“,value属性是一个枚举数组类型,写法如下: @MyAnnotation01({Weather.CLOUDY,Weather.RAIN}) public static void main(String[] args) { AnnotationTest01.method();//已过时 } }
10、使用反射机制获取注解
前提是这个注解已被Retention(RetentionPolicy.RUNTIME)注释,才可以用反射机制读取到
代码:
//创建一个类,被MyAnnotation02注释
@MyAnnotation02({"注解"}) public class AnnotationTest02 { public static void main(String[] args) { } }
//通过反射机制获取AnnotationTest02上的注解
public static void main(String[] args) { try { //第一步获取类 Class annotation=Class.forName("TwentyFiveDay.AnnotationTest02"); //判断AnnotationTest01有没有MyAnnotation02注解(这个注解必须是反射机制可以读取的!!!) if(annotation.isAnnotationPresent(MyAnnotation02.class)){ //获取MyAnnotation02的对象an MyAnnotation02 an = (MyAnnotation02)annotation.getAnnotation(MyAnnotation02.class); //获取注解对象的属性 String[] value = an.value(); System.out.println(value[0]);//注解 } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
11、注解作用的练习
自定义一个ID注解,这能标注类,作用是被标注的类必须有整型id属性,若是没有则报错“此类必须有整型id属性”;
//@ID
//这个注解只能标注类 @Target(ElementType.TYPE) //这个注解可以被反射机制读取 @Retention(RetentionPolicy.RUNTIME) public @interface ID { }
//user类
@ID public class UserClass { //int id; String name; }
//自定义异常类
//没有id整型属性异常 public class HasnotIDException extends RuntimeException { public HasnotIDException() { } public HasnotIDException(String s){ super(s); } }
//规定ID注解作用类
public static void main(String[] args) throws Exception { //获取UserClass类 Class user=Class.forName("TwentySixDay.UserClass"); //给个默认布尔型 boolean b=false; //属性集 Field[] fields=user.getDeclaredFields(); //判断有没有@ID注释 if(user.isAnnotationPresent(ID.class)) { //有注释,则遍历属性集 for (Field field : fields) { //判断有没有整型id属性 if("id".equals(field.getName())&&"int".equals(field.getType().getSimpleName())){ //如果走到这,则程序正常 b=true; } } } if(!b){ throw new HasnotIDException("此类必须有整型id属性!"); } }