jdk1.5的新特性(重点)
程序员文章站
2022-06-04 23:10:44
...
jdk1.5的新特性(重点):
1.自动装箱和拆箱
装箱:是把基本数据类型装箱成对象数据类型
拆箱:是把对象数据类型拆箱成基本数据类型
在jdk1.5及以后版本自动装箱和拆箱
int i=10;
Integer ii=i;
int k=ii;
在jdk1.5及以前版本必须手动自动装箱和拆箱
int i=10;
Integer ii=new Integer(i);
int k=ii.intValue();
2.增强for循环
for(类型 变量名:集合或数组){}
3.可变参数:
-用...定义
-本质就是一个数组
-可以传入任意个参数
-可变参数只能放在方发参数的最后一个位置
4.静态导入
-用import static 包名.类名.静态属性或静态方法名
-可以提高开发的效率
-降低了可读性,建议要慎用
5.枚举
switch(整型,字符型,枚举,1.7几以上版本可用字符串){}
enum
当取值为几个(有限)固定的值,可以使用枚举类型
枚举是一个数据类型
普通的枚举:
public enum RequestMethod{
GET,POST,DELETE,PUT
}
枚举也可以有方法和属性和构造函数
但是构造方法必须是私有的
枚举还可以实现接口,不能进行继承,枚举也可以包含抽象方法
所有枚举的类型都默认继承java.lang.Enum类
String name();
int ordinal();
6.反射:
java中提供一个套类库,通过这样的类库
- 运行时动态获取类中的信息
- 运行时动态调用构造函数,创建对象
- 运行时动态访问(调用)对象的方法和属性
这种运行期间动态获取类中的信息(属性,方法,包的信息,注解等),
以及动态调用对象的方法和属性的功能,称之为java语言的反射机制,通俗的理解,就是在运行期间对类的内容进行操作
Class类:
要使用反射,获取到类中的所有信息(属性,方法,注解等)
在java中有一个特殊的类 类型是Class,此类型的对象中存储的是某个类中的信息
比如:Class clazz = Class.forName("cn.tedu.Student");
clazz是一个对象,对象中存储的都是数据,这些数据都是Student中的属性和方法
属性:访问修饰符 类型 属性名
方法:访问修饰符,返回类型 方法名称(参数列表);
Class clazz = Class.forName("cn.tedu.User");
clazz存储的是User类中的信息
Class类是java提供的,这个Class类可表达任意一个类中的信息
- 每个类加载后(方法区),系统都会为该类生成一个对象的Class类型的对象,
这个对象存储在堆区中,通过该Class对象可以访问方法中的类的信息
- 一旦获取了某个类Class类型的对象之后,程序员可以写程序调用Class对象中的api方法,获取Class对象中的类的信息
- 所有的基本数据类型有Class对象
Class clazz = int.class;
* 如何获取Class类型的对象
- 对象.getClass();
比如:
User user = new User();
Class clazz = user.getClass();
- 类名.class
比如:
有一个类叫做User类
Class clazz = User.class
- Class.forName("包名.类名")
比如:
Class.clazz = Class.forName("cn.tedu.User");
以上3种获取Class类型的对象
类的加载分为两个步骤:
1. 把类加载到方法区中,并创建类的Class类型的对象
2. 把返回Class对象,用以上的3中方式获取Class对象
通过Class类型对象获取如下:
- field类:代表的成员变量,即属性
- Method类:代表的是方法
- Constructor类:代表的是构造方法
- Annotation类:代表的是注解
通过上面类的api方法获取数据
- 可以获取Field类中的信息, 获取类的属性 访问修饰符 属性的类型 属性的名称
- 可以获取Method类中的信息, 获取方法 修饰符 返回类型 方法名(参数列表)
- 可以获取Constructor中的信息,获取构造函数 修饰符 类名(参数列表)
- 可以获取Annotation中的信息, 获取注解 注解名称 注解的属性
结论:
在运行期间,通过Class对象调用反射的api
可以反射实例化对象
可以反射访问属性,和反射调用方法
总之,编译期间能写的代码,用反射也能实现
反射的api:
- 反射的方式创建对象
1.用无参数构造创建对象
Class对象.newInstance(); //常用的做法
2.用有参数构造创建对象
Class对象.getConstructor(new Class[]{若干参数的类类型}).newInstance(构造函数的参数);
比如:
//有参数构造
public User(String name,String password){
}
Class clazz = User.class;
//传统的实例化对象
User user = new User("yang","123");
//反射的做法
User user = clazz.getConstructor(new Class[]{String.class,String.class}).newInstance("yang","123");
- 反射的方式获取Field中的信息
1. 获取当前类以及长辈类的public Field
Field[] fields = Class对象.getFields();
2. 获取当前类中的所用的属性Field
Field[] fields = Class对象.getDeclaredFields()
3. 获取当前类以及长辈类中指定的公有属性
Field field = Class对象.getField(String fieldName);
4. 获取当前类中指定的属性
Field field = Class对象.getDeclaredField(String fieldName);
5. 通过反射设定Field属性
Field对象.set(Object obj,Object value);
如果Field是私有的,必须先执行: Field对象.setAccessable(true) //设置属性可以访问
6. 通过反射获取Field的值
Object value = Field对象.get(object);
如果Field是私有的,必须先执行: Field对象.setAccessable(true) //设置属性可以访问
- 反射方式获取Method方法信息
1. 获取当前类以及长辈类的public Method
Method[] methods = Class对象.getMethods();
2. 获取当前类中的所用的属性Method
Method[] methods = Class对象.getDeclaredMethods()
3. 获取当前类以及长辈类中指定的公有属性
Method method = Class对象.getMethod(String methodName,new Class[]{方法的参数类型});
4. 获取当前类中指定的属性
Method method = Class对象.getDeclaredMethod(String methodName,new Class[]{方法的参数类型});
5. 获取反射动态调用Method
Object returnValue = Method对象.invoke(Object,object...args);
解析:就是通过obj这个对象,调用Method对象确定的方法,给这个方法传递的参数是args
Method对象对应的方法的返回值returnValue;
- 反射获取Constructor构造函数
- 具体查看api文档
- 反射获取注解Annotation
- 具体查看api文档
- 反射的应用场景
- 用反射实现jdbc的通用查询和通用更新
- 单元测试,就是用反射实现的
- 常见的框架,spring框架,apringmvc框架都是用反射实现的
- EL表达式
反射的优点:
大幅度提高开发效率,框架就是反射实现的,框架可以大大提高开发效率
反射的缺点:
反射执行效率比非反射的方式执行效率低
反射可以暴露类中的所有细节,突破了封装
7.内省
就是自查的意思本质就是反射,利用反射自省类中的属性和方法
自省的方式有两种
方式一:
jdk(jre)中自带的一套自省的类库,类库包含的是api方法
侧重:属性和属性的值,属性所对应得getter和setter方法
方式二:
apache基金会提供的一套公有的自省类库CommonsBeanUtils.jar
他能够处理属性和属性的值和对应的getter和setter
还可以处理普通的方法
总结:1.能用Commons-BeanUtils就用就用此工具类
2.其次用java的原生的内省Introspector工具类
3.最后用java的原生的反射api Class Field Method Constructor
原生反射api是最灵活的
要开发快选择1方式
要灵活选择3方式
8.注解
注解应用场景很广泛,将来是一个趋势
他可以提高开发效率.但是执行效率堪忧,因为其底层解析注解时用反射解析的
用注解可以替换xml配置和属性文件
注解是一个标识,注解所代表的功能一定要用反射来实现
这些反射的代码,用于解析(寻找注解,获取注解的属性值)
然后根据注解设定的属性值来决定是否执行一些业务功能
使用注解的三个步骤:
1.用户定义注解 创建注解
2.把注解应用到对应的目标上 把注解放在什么地方(包,类,属性,方法,方法参数等)
3.用反射的代码来确定是否有注解和注解的属性值,根据是否有注解以及注解的值做相应的功能
如何定义注解:
//程序员创建注解
//设定MyAnnotation注解应用在什么位置上
@Target(value=ElementType.METHOD)
//指定注解的保留策略,source级别,class级别,runtime级别
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
元注解/源注解
@Target和@Retention和@Override等...都是元注解都是jdk自带的
[email protected](value={ElementType.Method,...})
指定修饰在什么样的目标上(包,注解,类/接口,方法,属性,参数等...)
value取值是一个枚举类型的数据
ElementType:
ANNOTATION 注解
METHOD 方法
FIELD 属性
CONSTRUCTOR 构造
TYPE 类/接口
PARAMETER 方法的参数上
[email protected](RetentionPolicy.RUNTIME)
注解保留策略
SOURCE:源代码级别,Source修饰的注解是给编译看的
编译器把源代码编完毕后,在class文件中就没有注解
CLASS:类级别,Class修饰的注解给类加载器看的
在类加载的时候可以做一系列的引导操作,
在编译器编译完毕后注解存在,在类加载加载之后就要丢弃注解
RUNTIME:运行时级别,给jvm看的,在程序运行的过程中做相关的操作
可以在jvm中借助反射api解析
注解中的属性详解:
a.注解定义属性和接口定义的方法类似,缺省默认public
public 类型 属性名称();
b.定义属性时,如果没有使用default指定默认值
则在使用注解,必须给属性赋值
如果没有默认值,是在使用注解的时候给属性赋值为新值,也可以是默认值
c.注解中的属性类型必须遵守如下要求
可以是八种基本数据类型,枚举类型,Class类型,String类型,
以及上面数据类型的一维 数组
d.在给数组赋值的时候,如果数组只有一个值就不用写{}
e.有一个极特殊的属性value
如果只为该属性赋值,value=值
但是如果注解只有value这一个属性,那么value可以省略
把注解应用到目标
在对应的目标上写上注解
@MyAnnotation(value="xx",name="yy",colors={"pink","green","gay"})
public class Demo1 {
private String str;
@MyAnnotation(value="aa",name="bb")
public void method1(String name){
}
public void method2(){
}
}
写反射代码来解析注解:
a.解析类上的注解
b.解析方法上的注解
9.泛型
一种参数化类型
//非泛型的写法,不是参数化的类型
ArrayList list0=new ArrayList();
list0.add("abc");
list0.add(10);//对象类型 Ieteger
//泛型标准的写法,标准参数化的类型,参数化类型指的是可以任意类型
ArrayList<String>list1=new ArrayList<String>();
list1.add("abc");
list1.add("aaa");
//list1.add(10);
//泛型的写法 不推荐
ArrayList list2=new ArrayList<String>();
list2.add("abc");
list2.add("aa");
list2.add(10);//语法是可以通过的
//泛型的写法,不推荐
ArrayList<String>list3=new ArrayList();
list3.add("abc");
list3.add("aa");
//list3.add(10);//语法是不通过
//下列的写法是错误的,编译报错,泛型两端的类型必须一致
//ArrayList<Object>list4=new ArrayList<String>();
自定义泛型
1.类上泛型,泛型类
泛型类一定要先定义,后使用,在类的名字后面定义泛型的类型
泛型的类型一定要是引用数据类型,不能是基本数据类型
定义在类上,在类的内部使用,在整个类范围内类型是一致的
类上的泛型的具体类型需要在创建类的对象的时候指定泛型具体类
如果在使用类上泛型是不指定泛型的具体类型,默认的具体类型为泛型的上边界
2.方法上的泛型,泛型上的方法
泛型要先定义后使用,在返回类型之前定义,通常用一个大写字母来定义一个泛型方法,可以定义多个,
且定义在方法上,在方法的内部使用,方法上泛型,在方法调用的时候自动推断出具体类型,无论如何
尽量使用泛型方法,因为泛型方法作用域小,只限于方法内部
T:类型 type
E:元素 element
K:关键字 key
V:值 value
..........
比如:
public <T,E> T save(T t,E e){
return t;
}
<T,E>就是标记,标记此方法就是一个泛型方法方法修饰符和返回类型之间可以放置多个符号
说明有多个参数化类型
泛型的上边界
泛型所取的类型是上边界或上边界类型的子类型
如果不指定泛型默认的上边界,默认是Object
泛型擦除
泛型编译期间起作用,真正执行期间泛型已经被擦除了
在编译阶段编译器会将所有使用泛型的地方替换为泛型的上边界
并在必要的时候增加上必要的类型转换和类型检查
所以在执行期间没有泛型的概念了
泛型在编译期间就被擦除掉了,此过程叫泛型的擦除
推荐阅读
-
Visual Studio 2017 针对移动开发的新特性汇总
-
SQL Server2012在开发中的一些新特性
-
HTML5自定义属性前缀data-及dataset的使用方法(html5 新特性)
-
结合CSS3的新特性来总结垂直居中的实现方法
-
PHP5各个版本的新功能和新特性总结
-
PHP 7的一些引人注目的新特性简单介绍
-
C# 7.0 新特性1之基于Tuple的“多”返回值方法
-
Visual Studio 2017 针对移动开发的新特性汇总
-
使用html5新特性轻松监听任何App自带返回键的示例
-
神经网络API、Kotlin支持,那些你必须知道的Android 8.1预览版和Android Studio 3.0新特性