黑马程序员---java学习笔记之java基础加强二
2014-01-17 13:58
369 查看
1、下面是我做的一个实验:
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、内省的简单操作
10、操作javaBean的第三方包BeanUtils
11、注解
12、自定义注解
13、注解分为三个阶段:RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME,分别对应的是java源文件,javaclass文件以及java字节码文件。默认的注解阶段是RetentionPolicy.CLASS
14、在自定义注解上加@Target(ElemetType[])可以对该自定义注解的位置进行设定。如下:
16、泛型入门示例代码:
17、集合后的泛型限定供编译器使用,以挡住非法输入,编译通过后就只能去掉集合后的泛型限定。
18、泛型限定使集合中只能存储一种类型的对象,反射可以在该集合中添加不同类型的对象,示例如下:
20、创建数组实例时,数组元素的类型是不能使用参数化类型的。意思就是
21、参数化类型与原始类型的兼容性
23、?为通配符,通配符可以设定上边界和下边界。
24、复习加泛型的应用:
a):Map.Entry
26、泛型方法中的类型参数只能接受对象,而不能接受基本数据类型的数据。下面是示例:
Integer i = 4; System.out.println(i.toString());上述代码,可以正常编译运行。
Integer i = 4; System.out.println((i+3).toString());上述代码不能够编译成功,说明代数式i+3在自动拆箱后并没有自动装箱。
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; 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; } }9、内省的复杂写法,使用BeanInfo
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; 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); } } }上述代码的打印结果是:@cn.itcast.day02.CustomAnnotation()
13、注解分为三个阶段:RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME,分别对应的是java源文件,javaclass文件以及java字节码文件。默认的注解阶段是RetentionPolicy.CLASS
14、在自定义注解上加@Target(ElemetType[])可以对该自定义注解的位置进行设定。如下:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) public @interface CustomAnnotation { }15、为注解添加属性值
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); String str = c.newInstance(new StringBuffer("123")); System.out.println(str);之所以选取这个代码示例,是想说明泛型不仅可以用在集合中,也可以用在非集合中。类Constructor不是集合也拥有自己的泛型指定类型。
17、集合后的泛型限定供编译器使用,以挡住非法输入,编译通过后就只能去掉集合后的泛型限定。
18、泛型限定使集合中只能存储一种类型的对象,反射可以在该集合中添加不同类型的对象,示例如下:
ArrayList<Integer> al = new ArrayList<Integer>(); 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]19、参数化类型不考虑类型参数的继承关系。
Vector<String> v1 = new Vector<Object>(); Vector<Object> v2 = new Vector<String>();上述两行代码都是错误的。
20、创建数组实例时,数组元素的类型是不能使用参数化类型的。意思就是
Vector<String>[] v1 = new Vector<String>[3];是不被允许的!
21、参数化类型与原始类型的兼容性
//原始类型引用可以接受一个参数化的类型 Vector v1 = new Vector<String>(); //参数的类型引用也可以接受一个原始类型 Vector<String> v2 = new Vector();22、下述两行代码可以编译通过
Vector v = new Vector<String>(); Vector<Object> v1 = v;原因是,编译器是一行行地编译的,单独一行不报错编译就不报错。
23、?为通配符,通配符可以设定上边界和下边界。
24、复习加泛型的应用:
a):Map.Entry
HashMap<String,Integer> map = new HashMap<String,Integer>(); 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()); }b):Iterator
HashMap<String,Integer> map = new HashMap<String,Integer>(); 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)); }25、
public static void main(String[] args) throws Exception { 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; }上述代码可以编译通过!为什么可以通过呢?根据add方法来看,不应该是两参数应该是相同类型的吗?为什么不同类型的也可以编译通过呢?在遇到这种情况时,返回值T取的是传入的两参数类型的“交集”(意思就是,可以包含两参数类型的类型,比如说,传入两参数类型分别是Integer和Float,那么可以包含这两种类型的类型就是Number及其父类)。
26、泛型方法中的类型参数只能接受对象,而不能接受基本数据类型的数据。下面是示例:
public static void main(String[] args) { 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; }第2个swap函数不能编译通过,第一个就可以。这验证了上面的观点,类型参数T只能够接受对象而不能接受基本数据类型的数据。
相关文章推荐