1、下面是我做的一个实验:
Integer i = 4;上述代码,可以正常编译运行。
System.out.println(i.toString());
Integer i = 4;上述代码不能够编译成功,说明代数式i+3在自动拆箱后并没有自动装箱。
System.out.println((i+3).toString());
Integer i = 4;上述代码是可以正常编译运行的。
i = i+3;
System.out.println(i.toString());
2、总结一下,反射的构造器、字段、以及方法的使用方式:
构造器创建对象使用的是:构造器对象.newInstance(Object... 参数名),字段获取某一对象的字段值使用的是:字段对象.get(Object 对象名),一般方法被对象调用的使用的是方法名.invoke(对象名,Object...参数列表)
3、反射的功能:实现框架的功能。怎么理解呢?开发人员要使用框架去开发项目,框架是在开发人员做项目之前就已经写好的。在框架中,我们写了自己的类,框架可以调用这些类,那为什么框架可以调用我们的类呢?框架是在我们类写出来之前就被写出来的,反射实现了这个细节,反射可以让开发人员调用还未写出来的类。
4、使用反射写框架时,给该工程创建一个配置文件,然后在主函数运行时,先导入该配置文件,读取该配置文件中的一些配置信息。这样主函数中就可以某些类名就可以有更大的范围。
5、获取配置文件有三种方式:1、使用FileInputStream;2、如果配置文件在classpath下,那么可以使用类加载器加载getClassLoader.getResoureAsStream(配置文件绝对路径名);3、直接使用类文件的getResourceAsStream(配置文件相对路径名)
6、所谓javaBean其实就是对具有某些特征的类的一种描述,这种特征是,该类中的某个变量XXX,有其setXXX和getXXX对其操作。javaBean有其独立的处理方式。
7、java为javaBean的处理方式提供了api,这些api称为内省。
8、内省的简单操作
import java.beans.IntrospectionException;9、内省的复杂写法,使用BeanInfo
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IntroSpectorDemo {
public static void main(String[] args) throws Exception {
//使用内省的方式获取javaBean类的属性值
Person p = new Person(23,"zhangsan");
String propertyName = "age";
Object temp = 25;
System.out.println(getProperty(p, propertyName));
setProperty(p, propertyName, temp);
System.out.println(getProperty(p, propertyName));
}
public static void setProperty(Object p, String propertyName, Object temp)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd1 = new PropertyDescriptor(propertyName,p.getClass());
Method methodSet = pd1.getWriteMethod();
methodSet.invoke(p,temp);
}
public static Object getProperty(Object p, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd = new PropertyDescriptor(propertyName,p.getClass());
Method methodGet = pd.getReadMethod();
Object objGet = methodGet.invoke(p, null);
return objGet;
}
}
class Person
{
private int age;
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static Object getProperty(Object p, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
BeanInfo bi =Introspector.getBeanInfo(p.getClass());
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
Object obj = null;
for( PropertyDescriptor pd : pds )
{
if( pd.getName().equals(propertyName) )
{
obj = pd.getReadMethod().invoke(p, null);
break;
}
}
return obj;
10、操作javaBean的第三方包BeanUtils
11、注解
//该注解可以在dos下编译程序时,遇到过时的方法不提示警告注解其实就是向编译器传递某种信息,另外,注解在以后的程序使用反射时被得到。
@SuppressWarnings("deprecation")
public static void main(String[] args) {
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);
}
//该注解可以使之后调用该方法的程序获得方法过时的警告!
@Deprecated
public void sayHello()
{
System.out.println("hello java");
}
//
@Override
public boolean equals(Object obj)
{
return this == obj;
}
12、自定义注解
import java.lang.annotation.Retention;上述代码的打印结果是:@cn.itcast.day02.CustomAnnotation()
import java.lang.annotation.RetentionPolicy;
//该注解是自定义注解的注解,称为“元注解”
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
}
@CustomAnnotation
public class AnnotationDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
if(AnnotationDemo.class.isAnnotationPresent(CustomAnnotation.class))
{
CustomAnnotation ca = (CustomAnnotation)AnnotationDemo.class.getAnnotation(CustomAnnotation.class);
System.out.println(ca);
}
}
}
13、注解分为三个阶段:RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME,分别对应的是java源文件,javaclass文件以及java字节码文件。默认的注解阶段是RetentionPolicy.CLASS
14、在自定义注解上加@Target(ElemetType[])可以对该自定义注解的位置进行设定。如下:
@Retention(RetentionPolicy.RUNTIME)15、为注解添加属性值
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface CustomAnnotation {
}
import java.lang.annotation.ElementType;为注解添加属性时,属性的返回值还可以是枚举类型的,注解类型的。
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//该注解是自定义注解的注解,称为“元注解”
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface CustomAnnotation {
//为注解添加属性值
String color() default "xyz";
String value();
int[] arrayA();
}
import java.util.Arrays;
@CustomAnnotation(value="123",arrayA = {7,8,9})
public class AnnotationDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
if(AnnotationDemo.class.isAnnotationPresent(CustomAnnotation.class))
{
CustomAnnotation ca = (CustomAnnotation)AnnotationDemo.class.getAnnotation(CustomAnnotation.class);
System.out.println(ca.color());
System.out.println(ca.value());
System.out.println(Arrays.toString(ca.arrayA()));
}
}
}
16、泛型入门示例代码:
Constructor<String> c = String.class.getConstructor(StringBuffer.class);之所以选取这个代码示例,是想说明泛型不仅可以用在集合中,也可以用在非集合中。类Constructor不是集合也拥有自己的泛型指定类型。
String str = c.newInstance(new StringBuffer("123"));
System.out.println(str);
17、集合后的泛型限定供编译器使用,以挡住非法输入,编译通过后就只能去掉集合后的泛型限定。
18、泛型限定使集合中只能存储一种类型的对象,反射可以在该集合中添加不同类型的对象,示例如下:
ArrayList<Integer> al = new ArrayList<Integer>();19、 参数化类型不考虑类型参数的继承关系。
al.add(1);
al.add(2);
al.add(3);
System.out.println(al);//打印结果是:[1, 2, 3]
al.getClass().getMethod("add",Object.class).invoke(al, "abc");
System.out.println(al);//打印结果是:[1, 2, 3, abc]
Vector<String> v1 = new Vector<Object>();上述两行代码都是错误的。
Vector<Object> v2 = new Vector<String>();
20、创建数组实例时,数组元素的类型是不能使用参数化类型的。意思就是
Vector<String>[] v1 = new Vector<String>[3];是不被允许的!
21、参数化类型与原始类型的兼容性
//原始类型引用可以接受一个参数化的类型22、下述两行代码可以编译通过
Vector v1 = new Vector<String>();
//参数的类型引用也可以接受一个原始类型
Vector<String> v2 = new Vector();
Vector v = new Vector<String>();原因是,编译器是一行行地编译的,单独一行不报错编译就不报错。
Vector<Object> v1 = v;
23、?为通配符,通配符可以设定上边界和下边界。
24、复习加泛型的应用:
a):Map.Entry
HashMap<String,Integer> map = new HashMap<String,Integer>();b):Iterator
map.put("zhangsan", 24);
map.put("lisi", 20);
map.put("wangwu", 29);
map.put("zhaoliu", 26);
Set<Map.Entry<String,Integer>> mapSets = map.entrySet();
for(Map.Entry<String,Integer> mapSet:mapSets )
{
System.out
.println(mapSet.getKey() + " : " + mapSet.getValue());
}
HashMap<String,Integer> map = new HashMap<String,Integer>();25、
map.put("zhangsan", 24);
map.put("lisi", 20);
map.put("wangwu", 29);
map.put("zhaoliu", 26);
Set<String> keySet = map.keySet();
Iterator<String> it= keySet.iterator();
while(it.hasNext())
{
String str = it.next();
System.out.println(str+" : "+map.get(str));
}
public static void main(String[] args) throws Exception {上述代码可以编译通过!为什么可以通过呢?根据add方法来看,不应该是两参数应该是相同类型的吗?为什么不同类型的也可以编译通过呢?在遇到这种情况时,返回值T取的是传入的两参数类型的“交集”(意思就是,可以包含两参数类型的类型,比如说,传入两参数类型分别是Integer和Float,那么可以包含这两种类型的类型就是Number及其父类)。
add(1,2);
Number n = add(4.1,4);
Object obj = add(5,"123");
}
private static <T> T add(T a, T b)
{
return a;
}
26、泛型方法中的类型参数只能接受对象,而不能接受基本数据类型的数据。下面是示例:
public static void main(String[] args) {第2个swap函数不能编译通过,第一个就可以。这验证了上面的观点,类型参数T只能够接受对象而不能接受基本数据类型的数据。
swap(new String[]{"123","abc","789"},1,2);
swap(new int[]{1,2,3,4},1,2);
}
public static <T> void swap(T[] arr, int i, int j)
{
//这个函数的作用是交换给定数组的两个元素的位置
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}