jdk1.5新特性
作者:互联网
自动拆箱和装箱
拆箱原理:把类类型拆开,变成基本数据类型
即把对象中的数据拆出来变成基本数据类型,
装箱原理:把基本数据类型的数据封装成对象数据
比如:
方式一:
Integer i=new Integer(3);
//把基本数据类型的3装箱成对象i
int ii=i.intvalue();
//把i中的数据3转换成基本数据类型的ii
方式二:
Integer k=3;//装箱
int kk=k;//拆箱
方式一的写法在任意版本都能使用
方式二的写法只能在jdk1.5及以上的版本才能使用
此方式是属于自动装箱和拆箱
增强for循环
语法:
for(数据类型 变量名: 数组名或者集合名){
//循环体代码块
}
说明:
从数组或者集合中去除第一个数据,赋值给变量名
然后从循环体代码块中使用次变量名中的数据(变量名作用范围仅在循环体范围内),执行完循环体,后再次从数组或者结合中去除第二个数据,赋值给变量名,然后在循环体中使用变量名中的数据
以此往复,知道把数组中的数据都取出,循环执行完毕
注意
变量名所对应的数据类型必须和数组或集合中的数据类型相同,
可变参数
-用…来定义
-其本质是一个数组
-可以传入任意多个的参数
-可变参数只能放在方法参数的最后一个位置(遍历使用增强for循环)
静态导入
-静态导入格式: import static 包名.类名.静态属性或者静态方法名
-提高了加载效率,静态导入的变量随着类的加载而加载到方法区
-降低了可读性,慎用,程序员不知道静态导入的属性是什么用途
-建议使用类名打点调用静态的方法和熟悉
枚举: enum
当取值为几个(有限个)固定的值,可以使用枚举类型
枚举类型是一个数据类型
普通的枚举:
public enum RequestMethod{
GET,POST,DELETE,PUT
}
public enum Week{
Monday,Tuesday,Wednesday,Thursday,Firday,Saturday,Sunday
}
枚举也可以实现接口,但是不能进行继承,枚举也可以包含抽象方法
所有自定义的枚举类型都默认继承java.lang.Enum类
String name(); 返回当前枚举类型的字符串
int ordinal(); 返回当前枚举类型在枚举类中的位置
反射:
什么是反射:
java中提供的一套类库,通过这套类库可以做:
运行时动态获取类中的信息
运行时动态调用构造函数创建对象
运行时动态访问/调用对象的方法和属性
这种运行期间动态获取类中的信息(属性,方法,包,注解)以及动态调用对象的方法和属性的功能称之为java的语言但是机制,通俗的理解就是在运行期间对类的内容进行操作
Class类:
要想使用反射们就要获取类中的所有信息(属性,方法)
在java中有一个特殊的类类类型,是Class,
此类型的对象存储的是某个类中的信息
比如:
Class clazz1=Class.forName("cn.tedu.Student");
clazz1 是一个Class类型的对象
对象中存储的都是数据,
但是这些数据都是Student的属性和方法
属性:访问修饰符,类型,属性名,
方法:访问修饰符,返回类型,方法名,参数列表
Class clazz2=Class.forName("cn.tedu.User");
clazz2 是一个Class类型的对象
对象中存储的是User的属性和方法
-Class类是java提供的,这个Class类可以表达任意一个类的信息(方法和属性)
每个类加载后(方法区),系统都会为该类生成一个
Class类类型的对象
这个对象存储在堆区中,通过该claa对象,可以访问方法区中的信息
-一旦获取了某个Class类类型 的对象之后,程序员可以写程序调用Class对象中的api方法
获取给Class对象中的类的信息.
-所有的基本数据类型也有Class对象
Class clazz = int.getClass();
如何获取Class类型的对象
-对象.getClass();
比如 User user=new User();
Class clazz1=user.getClass();
-类名.Class
比如:
有一个类User,
Class clazz=User.class;
-Class.forName("包名.类名")
比如:
Class clazz=Class.forName("cn.tedu.User");
此种情况分两步:
1.加载类User进方法区,创建Class类型的对象
2.把Class类型的对象
用以上的三种方式,可以获取到Class类型的对象
通过Class类型的对象获取如下信息:
-Field类:代表的是成员变量,即属性
-Method类:代表的是方法
-Constructor类:代表的是构造函数
-Annotation类:代表的是注解
通过上面的类的api获取对应的信息
-获取Field中的信息,获取类的属性,属性的修饰符,属性的类型,属性的名称
-获取Method中的信息,提取类的方法,修饰符,返回类型,参数列表
-获取Constructor中的信息,获取构造函数,修饰符,构造函数的参数列表
-获取Annotation中的信息,获取注解的明后才能,注解属性值
结论:
运行期间,调用Class对象调用反射的api
可以反射实例化对象,可以反射调用属性和方法
总之,编译期间能写的代码,用反射也能实现
介绍反射的常规api:
-反射方式创建对象
1.用无参构造创建对象
Class对象.newInstance();//常用
2.有参构造创建对象
Class对象.getConstructor(new Class[]{若干参数的类类型})
比如:
User user=new User("张三","zs");
user.getClass().getConstructor(
new Class[]{String.class,String.class }).newInstance("张三","zs");
-反射方式获取Field中的信息:
1.获取当前类及长辈类的public Field
Field[] field=Class对象.getField();
2.获取当前类中的所有的属性Field
Field[] fields=Class对象.getDeclaredFields();
3.获取当前类以及长辈类中指定的公有属性
Field field=Class.getField(String fieldName);
4.获取当前类中指定的属性
Field field=Class.对象.getDeclaredField(String fieldName);
5.通过反射设定Field属性的值
Field对象.setObject(Object obj,Object value);
如果Field是私有的,必须先执行:
Filed对象.setAccessable(true);//设置属性可以访问
6通过反射动态获取Field的值
Object value=Filed对象.get(Object obj);
如果Field是私有的,必须先执行:
Filed对象.setAccessable(true);//设置属性可以访问
-反射方式获取Method方法的信息
1.获取当前类及长辈类的公有方法
Method[] methods=Class对象.getMethods();
2.获取当前类中的所有方法
Method[] methods=Class对象.getDeclaredMethods();
3.获取当前类及长辈类中指定的公有方法
Method method=Class对象.getMethod(String methodName,new Class[]{methodName的参数类型});
4.获取当前类中指定的方法
Method method=Class对象.getDeclaredMethod(String methodName,new Class[]{methodNamed的参数类型});
5.通过反射动态调用指定的Method
Object returnValue=Method对象.invoke(Object obj,Object...args);
解析:
通过obj这个对象调用Method对象确定的方法,给这个方法传递args参数
Method对象对应的方法的返回值是returnValue
-反射获取Construetor构造函数
查api文档
-反射获取Annotation注解
查api文档
在哪些地方使用反射,反射的应用场景
-反射实现jdbc的通用查询和通用更新
-反射解析注解
-单元测试,用反射实现
-常见的框架,spring springmvc等其他框架,用反射实现
-EL表达式
-等等
反射的优点:
大幅度的提高开发效率,框架就是用反射实现的,框架提高了开发效率
反射的缺点:
反射的效率比非反射的方式的执行效率低
反射可以暴露类中的所有的细节,突破了封装
2019/07/27
内省:就是自查的意思,本质就是反射,利用反射自省类中的属性和方法
自省的实现方式:
方式一:
jdk(jre)中自带的一套自省的类库,类库中包含的api方法
侧重:属性和属性的值以及属性所对应的getter和setter方法
方式二:
apache基金会提供的一套公共的自省类库,Commons-Beans.jar
注解:将来的发展趋势
用注解可以替换xml配置和属性文件的配置
用注解开发代码效率很高
注解实际上就是一个标识,注解所代表的功能是用反射代码实现的
这段反射代码用于解析注解(找到并确定注解的存在),
根据注解设定的属性来决定做什么样的功能
使用注解的步骤
1.如何定义注解(创建注解)
右键单击创建Annotation
//代表此注解可以修饰的目标,类,方法上
@Target({ElementType.TYPE,ElementType.METHOD})
//此注解保留策略,在运行期间能够使用
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnontation {
//在注解中可以放置注解的属性
public String value();//是属性,不是方法
public String name() default "abc" ;
public String[] colors() default {"red","blue"};
}
源注解/元注解:用于修饰注解的注解,jdk自带的注解
@Target(ElementType.xxx) 把注解应用在什么目标上
@Target({ElementType.xxx,ElementType.xxx1}) 把注解应用在什么目标上
@Retention(RetentionPolicy.RUNTIME) 注解的保留策略
被他修饰的注解保留区域
编译器 类加载 jvm
.java -->.class-->加载-->运行
SOURCE:源码级别,给编译器看的,编译完成后直接丢弃该种注解,
生成的.class文件没有该类型的注解
CLASS:给类加载器看的,在类加载的时候进行的一系列引导操作
编译器编译后存在,类加载器完成加载之后,丢弃该保留区域的注解
RUNTIME:给jvm看的,在程雪运行过程中做相关的操作
类加载器加载后保留,在jvm运行时通过反射技术反射出使用的是什么注解
,注解的属性值是什么,根据他们两个的值做对应的操作
@Documented:自定义的注解,如果使用Documented注解生成的doc文档上,使用该自定义注解的地方会显示注解信息,如果去掉@Ducumented,生成的doc文档将不再有注解信息
注解中的属性详解:
a.注解定义属性和接口中定义方法类似,缺省默认public
public 类型 属性名称();
b.定义属性时,如果没有使用default指定默认值
使用当前注解必须为该属性赋值
(可以利用该特点,设置必须赋值的属性不要使用default指定默认值)
使用default指定默认之后,该属性在注解使用时可以赋值
也可以不赋值
c.注解中的属性类型是有要求的
可以是八种基本数据类型,可以是枚举类型,Class类型,String类型等
以上类型的"一维"数组,如String[] likes() default {};
使用注解时,如果数组类型的属性的值是一个值的话
赋值时可以吧"{}"省略掉,@Anoo1(name="zs",likes="fb")
d.
2.把注解应用在对应的目标上 (把注解放在什么地方)
在对应的目标写
@注解的名称(属性名=属性值)
@注解的名称(属性名1=属性值1,属性名2=属性值2,....属性名n=属性值n)
3.通过反射的api解析注解 (有注解标识就做对应的功能)
参见项目代码
总结:用注解就是根据注解和注解上的属性值,来决定是否做一些事
可以是指行指定的功能,也可以是调用一个具体方法
注解:1.自定义注解 2.应用注解 3.解析注解
泛型:一种参数化的类型
//非泛型,不是参数化类型
ArrayList list=new ArrayList();
list.add("abc");
list.add(10);
//泛型版本 标准做法 参数化类型 String类型
ArrayList<String> list1=new ArrayList<String>();
list1.add("abc");
list1.add("bcd");
//泛型,不推荐
ArrayList list2=new ArrayList<String>();
list2.add("abc");
list2.add(10);
new Demo01().xxx(list1);
new Demo01().xxx(list2);
//泛型,不推荐
ArrayList<String> list3=new Demo01().yyy();
list3.add("abc");
//错误做法,编译报错
//两边的泛型必须一致
//ArrayList<Object> list4=new ArrayList<String>();
自定义泛型:
-类上的泛型,泛型类
泛型一定要先定义后使用,在类的名字后面定义
泛型的类型一定要是引用数据类型,不能是基本数据类型
不能对确切的反省类型使用instanceof关键字
比如:
//此种写法语法报错
if(num instanceof Generic<Number>){
}
定义在类上,在类的内部起作用,在整个类范围的内类型一致
类上的泛型的具体类型要在创建类的对象的时候指定泛型的具体类型
如果在使用类上的泛型时不指定泛型的具体类型,
默认的具体类型为泛型的上边界
-方法上的泛型,泛型方法
泛型要先定义后使用,在返回值之前定义,通常是用一个大写字母来定义一个泛型
可以定义多个,且定义在方法上,在方法内部起作用
方法上的泛型在方法被调用的时候自动推断出具体的泛型
无论何时,尽量使用泛型方法,方法泛型的作用域小,只局限于本方法内
比如:
public<T> T save(T t){
return t;
}
<T>就是标志此方法是一个泛型方法,放在修饰符和返回类型之间
可以放置多个符号,<T,E>,说明有两个类型需要参数化确定
泛型的上边界:
泛型所取得类型是上边界或者上边界类型的子孙类型,如果不指定泛型默认上边界是Object
泛型擦除:
泛型在编译期间起作用,真正执行期间泛型已经被擦除了
在编译阶段,编译器会将所有使用泛型的地方替换为该泛型的上边界
并在必要的时候增加上必须的类型强制转换和类型检查
在执行期间没有泛型的概念了
泛型在编译期间就被擦除掉了
此过程叫做泛型擦除
标签:反射,特性,jdk1.5,类型,泛型,注解,Class,属性 来源: https://blog.csdn.net/qq_44374349/article/details/97557758