1、反射(reflect):(利用配置文件)
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以
对一个类进行解剖,把各个组成部分映射成一个个对象。
主要应用于框架,框架基于配置文件。
加载类:
//加载类的字节码
//1 常用
Class classz1 = Class.forName("seu.xinci.reflect.person");
//2
Class classz2 = Person.class;
//3
Class callsz3 = new Person().getClass();
解剖类:
得到public:
Constructor getConstructor
Method getMethod
Field getField
得到private:
Constructor getDeclaredConstructor
Method getDeclaredMethod
Field getDeclaredField
获得构造方法:
@Test //反射类无参的构造方法 public Person()
public void test1() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//利用Constructor创建对象
Class classz = Class.forName("seu.xinci.reflect.Person");
Constructor constructor = classz.getConstructor();
Object o = constructor.newInstance(null);
System.out.println(o);
}
@Test //反射类有参的构造方法 public Person(String name)
public void test2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//利用Constructor创建对象
Class classz = Class.forName("seu.xinci.reflect.Person");
Constructor constructor = classz.getConstructor(String.class); //制定参数类型,不是变量名称
Person o = (Person) constructor.newInstance("aa");
System.out.println(o);
}
@Test //反射类私有的、有参的构造方法 private Person(int name)
public void test3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//利用Constructor创建对象
Class classz = Class.forName("seu.xinci.reflect.Person");
Constructor constructor = classz.getDeclaredConstructor(int.class); //制定参数类型,不是变量名称
constructor.setAccessible(true); //暴力反射
Person o = (Person) constructor.newInstance(25);
System.out.println(o);
}
获得构造方法:
//反射无参 public void eat()
@Test
public void test() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class classz = Class.forName("seu.xinci.reflect.Person"); //带包的名称:完整名称
Person person = (Person) classz.newInstance();
Method eat = classz.getMethod("eat", null);
eat.invoke(person,null);
}
<pre name="code" class="java">//反射有参 public void run(String address)
@Test
public void test2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person"); //带包的名称:完整名称
Method eat = classz.getMethod("run", String.class);
eat.invoke(person,"北京");
}
</pre><pre>
//反射有参带返回值 public String test(String string)
@Test
public void test3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person"); //带包的名称:完整名称
Method eat = classz.getMethod("test", String.class);
String cs = (String) eat.invoke(person, "北京");
System.out.println(cs);
}
//反射有参带返回值、私有方法 private String test2(String string)
@Test
public void test4() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person"); //带包的名称:完整名称
Method eat = classz.getDeclaredMethod("test2", String.class);
eat.setAccessible(true); //暴力反射
String cs = (String) eat.invoke(person, "北京");
System.out.println(cs);
}
//反射有参带返回值、静态方法 public static String test3(String string)
@Test
public void test5() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person"); //带包的名称:完整名称
Method eat = classz.getDeclaredMethod("test3", String.class);
String cs = (String) eat.invoke(null, "北京");
System.out.println(cs);
}
//反射mian方法 public static void main(String[] args)
//通过反射调用带数组的方法时,要注意处理
@Test
public void test6() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person"); //带包的名称:完整名称
Method eat = classz.getDeclaredMethod("main", String[].class);
eat.invoke(null, (Object) new String[]{"1","2"});
}
传一个数组容易出问题,因此,如果只传一个数组那么就要欺骗。(Object)
获得反射成员变量:
//反射类的字段 ---set public String name;
@Test
public void test1() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person");
Field name = classz.getField("name");
name.set(person,"fix");
System.out.println(person.getName());
}
//反射类的字段 ---get public String name;
@Test
public void test2() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Person person = new Person();
person.setName("xxx");
Class classz = Class.forName("seu.xinci.reflect.Person");
Field name = classz.getField("name");
String o = (String) name.get(person);
System.out.println(o);
}
//反射类的字段 ---set private int age;
@Test
public void test3() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Person person = new Person();
Class classz = Class.forName("seu.xinci.reflect.Person");
Field name = classz.getDeclaredField("age");
name.setAccessible(true);
name.set(person,123);
System.out.println(person.getAge());
}
//反射类的字段 ---get private int age;
@Test
public void test4() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Person person = new Person();
person.setAge(123);
Class classz = Class.forName("seu.xinci.reflect.Person");
Field age = classz.getDeclaredField("age");
age.setAccessible(true);
int o = (Integer) age.get(person);
System.out.println(o);
}
2、内省(introspector):
用于操作javabean对象。
有什么get、set方法就有什么属性。
- 直接调用bean的setXXX或getXXX方法。
- 通过内省技术访问(java.beans包提供了内省的API),内省技术访问也提供了两种方式。
- 通过PropertyDescriptor类操作Bean的属性
- 通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
//通过内省api操作bean的name属性
@Test
public void test1() throws IntrospectionException, InvocationTargetException, IllegalAccessException {
Student s = new Student();
PropertyDescriptor pd = new PropertyDescriptor("name",Student.class);
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(s,"flx");
//System.out.println(s.getName());
Method readMethod = pd.getReadMethod();
String result = (String) readMethod.invoke(s, null);
System.out.println(result);
}
类继承object,object中有getClass(),所以会有class属性
//操作bean的所有属性
@Test
public void test2() throws IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(Student.class);
PropertyDescriptor[] pd = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor is:pd){
System.out.println(is.getName());
}
}
3、BeanUtils:
Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。
所需文件:beanutils(commons-beanutils-1.9.2.jar),log4j(commons-logging.jar) (Apache公司)
实例:
//用beanUtils操作bean
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Student s = new Student();
BeanUtils.setProperty(s, "name", "flx");
System.out.println(s.getName());
}
自动的类型转换! 例如下面例子中的age字段!!以下代码中的birthday是错误示例!!!
//用beanUtils操作bean
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
String name = "flx";
String password = "123";
String email = "flx@sina.com";
String age = "21";
String birthday = "1990-09-19";
Student s = new Student();
BeanUtils.setProperty(s, "name", name);
BeanUtils.setProperty(s, "password", password);
BeanUtils.setProperty(s, "email", email);
BeanUtils.setProperty(s, "age", age);
BeanUtils.setProperty(s, "birthday", birthday);
System.out.println(s.getAge());
System.out.println(s.getBirthday());
}
可以自动进行8中基本类型的转换。但是birthday这种String类型的转换就不可以实现。
除了 这四类八种基础类型,剩下的java 一切类型 都是引用类型。那么 这四类八种基础数据类型是什么呢? 请看下面
第一类:整型 byte short int long
第二类:浮点型 float double
第三类:逻辑型 boolean(它只有两个值可取true false)
第四类:字符型 char
示例: ConverUtils 注册转化器!!! //用beanUtils操作bean
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
String name = "flx";
String password = "123";
String email = "flx@sina.com";
String age = "21";
String birthday = "1990-09-19";
Student s = new Student();
ConvertUtils.register(new DateLocaleConverter(),Date.class);
BeanUtils.setProperty(s, "name", name);
BeanUtils.setProperty(s, "password", password);
BeanUtils.setProperty(s, "email", email);
BeanUtils.setProperty(s, "age", age);
BeanUtils.setProperty(s, "birthday", birthday);
System.out.println(s.getAge());
System.out.println(s.getBirthday());
}
不能new接口的原因是接口里面有抽象的方法,但是如果我们在new的时候把抽象的方法实现了,那么就可以了。
实现自己的Convert转换器:
//用beanUtils操作bean
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
String name = "flx";
String password = "123";
String email = "flx@sina.com";
String age = "21";
String birthday = "1990-09-19";
Student s = new Student();
ConvertUtils.register(new Converter() {
public Object convert(Class type, Object value) {
if (value == null)
{
return null;
}
SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd");
Date date = null;
try {
date = formatter.parse((String) value);
} catch (ParseException e) {
throw new ConversionException(e);
}
return date;
}
}, Date.class);
BeanUtils.setProperty(s, "name", name);
BeanUtils.setProperty(s, "password", password);
BeanUtils.setProperty(s, "email", email);
BeanUtils.setProperty(s, "age", age);
BeanUtils.setProperty(s, "birthday", birthday);
System.out.println(s.getAge());
System.out.println(s.getBirthday());
}
操作bean的属性优先选用beanUtils
对于8种基本类型,用自带转换器。如果实在没有找到,自己去写。
4、泛型(generic):
为了保证程序的安全性,最典型的应用场景就是集合。 <>念着typeof
JDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序
运行时可能发生
问题,转变为
编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。
泛型是给编译器用的。
编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。
整个ArrayList<Integer>称为参数化的类型ParameterizedType。
//泛型典型应用1 单列
@Test
public void test1(){
List<Integer> list = new ArrayList<Integer>();
list.add(1);
int i = list.get(0);
}
取map集合一定用的是entryset()!!!
//泛型典型应用2 双列
@Test
public void test2(){
Map<String,Integer> map = new LinkedHashMap<String, Integer>();
map.put("a",1);
map.put("aa",2);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> i:entries){
String key = i.getKey();
Integer value = i.getValue();
System.out.println(key + "=" + value);
}
}
使用泛型的注意事项:
- 使用泛形时,泛形类型须为引用类型,不能是基本数据类型。
- 定义变量只用对象,到底能调用什么方法由变量决定的。 一旦用到泛型,左右两边都应该一致,除非只用一边。
//ArrayList<String> list = new ArrayList<Object>(); 错误示例
//ArrayList<Object> list = new ArrayList<String>(); 错误示例
ArrayList<String> list = new ArrayList ();
ArrayList list = new ArrayList<String>();
自定义泛型:
1、编写一个泛型方法,交换数组上的任意两个的元素。
public static void main(String[] args) {
Integer arr1[]={1,2,3};
swap(arr1,0,1);
System.out.println(Arrays.asList(arr1));
Byte arr2[]={'a','b','c'};
System.out.println(Arrays.asList(arr2));
}
//编写一个泛型方法,交换数组上的任意两个位置的元素 不能确定传入数组的类型
@Test
public static <T> void swap (T arr[],int pos1,int pos2){
T temp = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = temp;
}
2、编写一个泛型方法,接收一个任意数组,并颠倒数组中的所有元素:
public class Demo2 {
public static void main(String[] args) {
Integer arr[] = {1,2,3,4};
swap(arr);
System.out.println(Arrays.asList(arr));
}
//编写一个泛形方法,接收一个任意数组,并颠倒数组中的所有元素
public static <T> void swap (T arr[]){
int start = 0;
int end = arr.length-1;
while(start <= end)
{
T temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
}
只有对象类型才能作为泛型方法的实际参数。
在泛型中可以同时有多个类型,例如:
public static <K,V> V getValue(K key) { return map.get(key);}
在类上面定义的泛型只对类的非静态成员有效!! 静态不需要进行new,也就不知道T
如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下:
public class GenericDao<T> {
private T field1;
public void save(T obj){}
public T getId(int id){}
}
如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下:
public class GenericDao<T> {
private T field1;
public void save(T obj){}
public T getId(int id){}
}