黑马程序员_07 Java高新技术1

-------  android培训、 java培训、期待与您交流! ----------

08. java5的静态导入与编译器语法设置: 用于简化程序对类静态属性和方法的调用

     import语句可以导入一个类或某个包中所有类

     import static语句导入一个类中某个静态方法和属性或所有静态方法和属性

          语法:import static 包名.类名.静态属性|静态方法|*

          例如 

               import static java.lang.System.out

               import static java.lang.Math.*    

09. 可变参数与OverLoad相关面试题分析     

     可变参数的特点:

  •      只能出现在参数列表的最后;

  •      位于变量类型和变量名之间, 前后有无空格都可以

  •      调用可变参数的方法时, 编译器为该可变参数隐式创建数组, 在方法体中以数组形式访问可变参数.

//2.可变参数

public class D2VarableParameter {
     
     public static void main(String[] args) {
           int sum = max(2,4,5,8);
          System. out.println( "sum=:"+sum);
     }    
     public static int max(int... arr){
           int sum = 0;
           for(int i=0;i<arr.length;i++)
              sum += arr[i];
           //打印这句话说明arr确实是变成了数组
          System. out.println(arr);
           return sum;
     }
}

     overload与override的分析

          一个是函数的重载, 一个是函数的重写覆盖.

10. java5的增强for循环

     语法:

          for(type 变量名: 集合变量名){... }

     注意:

          迭代变量必须定义在( )中, 集合变量只能是数组或实现了Iterator接口的集合类

11. 基本数据的自动拆装箱及享元设计模式

     自动装箱:

          Integer num = 123;

     自动拆箱

          System.out.println(num+1);

Integer num=12;
Integer num2=12;
num==num2为true
Integer num=128;
Integer num2=128;
num==num2为false
Integer num=Integer.valueOf(12);
Integer num2=Integer.valueOf(12);
num==num2为true
Integer num=Integer.valueOf(128);
Integer num2=Integer.valueOf(128);
num==num2为false

可以得知Integer -128~127 内,用==为true, 其他为false,

 由此牵涉到了flyweight享元设计模式: 公有的就公有称为内部状态,对于不同的属性的则封装在方法里称为外部状态.

12.枚举的作用介绍

     枚举就是让某个类型的变量的取值只能为若干规定的值,否则编译器就会报错.枚举可以让编译器在编译时期控制源程序填写是否是非法制,而是用普通变量的方法无法在开发阶段实现此目标
13.用普通类模拟枚举的实现原理

     1. 定义每个元素,应该是公有静态成员变量

     2.私有构造方法

     3.可以有若干公有或抽象方法, 例如提供nextDay方法必须是抽象的.采用抽象方法定义nextDay就将大量的if else语句转移成一个个独立的类.
14.java5的枚举的基本应用

     枚举相当于一个类,枚举里面的元素相当于一个对象.
15.实现带有构造方法的枚举

     使用private 类名(){}

     枚举元素后加入小括号,就是指定该元素用的是哪个构造方法.
16.实现带有抽象方法的枚举

     定义抽象方法后,每个枚举元素写成:

             元素{ 

                          //要实现的抽象方法

                          ...     

                     }      

//该是最复杂的枚举
     public enum TrafficLamp{
           RED(30){
               public TrafficLamp nextLamp(){
                    return GREEN ;
              }             
          }, GREEN(45) {
               public TrafficLamp nextLamp() {
                    return YELLOW ;
              }
          }, YELLOW(5) {
               public TrafficLamp nextLamp() {
                    return RED ;
              }
          };
              
           private int time;
           //每个对象在使用前都调用该构造函数,表现在第一行每个对象后一对小括号,而后的大括号是匿名内部类.
           private TrafficLamp(int time){
               this.time = time;
          }
           public abstract TrafficLamp nextLamp();
     }

wKioL1QEGvbTbqKZAAILh1DfGTU094.jpg

17.透彻分析反射的基础_Class类

Class类就代表Java类,表示Java类的Class类要提供一系列方法来获取其中的变量,方法,构造方法,,修饰符,包等信息,这些信息就是相应类的实例对象来表示.Field,Method

Contructor,Package

如何获得各个字节码对应的实例对象(Class类型)

     类名.class, 例如System.class

     对象.getClass(), 例如 new Date().getClass()

     (最为常用)Class.forName("类名"), 例如 Class.forName("java.util.List");

九个预定义Class实例对象

     byte.class;     short.class;

     int.class;     long.class;

     float.class;     double.class;

     char.class;     boolean.class;     void.class;

只要是源程序中出现的类型,都有各自的Class实例对象.

           String str1 = "abc";
           //三种方法得到都是String 类 类型.
           Class cls1 = str1.getClass();
           Class cls2 = String.class;
           Class cls3 = Class.forName ("java.lang.String" );
          
          Integer a = 9;
          Integer b = 54;
          System. out.println(a.getClass() == b.getClass());
          
          System. out.println(cls1 == cls2);
          System. out.println(cls1 == cls3);
           //以上三个输出指出每种类型的Class对象只有唯一一份
          
          System. out.println(Void.class == void. class);   
           //两者比较返回false
          System. out.println(short .class == Short.TYPE);
           //而每种基本数据类型 和 对应包装类的Type静态属性返回true
          System. out.println(Void.class.getClass().getName());
           //isPrimitive判定指定的 Class对象是否表示一个基本类型
          System. out.println(void .class.isPrimitive());
           //isArray判断是否是数组类型
          System. out.println(int [].class.isArray());

18.理解反射的概念

     一个类中每个成员变量都可以通过相应的反射API类的一个实例对象表示,我们就能得到相应的实例对象.拿到实例对象,我们然后.

19.构造方法的反射应用

     Constructor类代表某个类中的一个构造方法 

 //获取所有pullic的构造方法
          Constructor<?>[] constructors = Class.forName("java.lang.String").getConstructors();
           //获取某个构造方法
          Constructor<?> c = Class.forName("java.lang.String").getConstructor(StringBuilder. class);
          
           // 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符
           //System.out.println(c.getModifiers());
          
           //返回 Class 对象,该对象表示声明由此 Constructor 对象表示的构造方法的类。
           //System.out.println(c.getDeclaringClass().toString());
          
           //反射方式建立实例对象
          String str = (String)c.newInstance(new StringBuilder("kuwo" ));
          System. out.println("通过constructor的newInstance方法得到 " +str);
          
           //Class.newInstance()方法是采用默认的构造方法然后得到实例.
          Class.forName("java.lang.String").newInstance();

20.成员变量的反射     

     Field类代表类中的一个成员变量.Filed对象对应到某个对象上的成员变量   

public static void method2() throws Exception{
           Class clazz = Class.forName("itcast.day1.Person");
          
           //返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。name 参数是一个 String,用于指定所需字段的简称。
          Field fieldAge = clazz.getField( "country");     
           //Object get(Object obj)返回 指定对象上 此 Field 表示的字段的值
          System. out.println("country=" +fieldAge.get(new Person("likai","YongZhong" ,22,52)));
          
           //getDeclaredField可以忽略private
          Field fieldName = clazz.getDeclaredField( "name");
           //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
          fieldName.setAccessible( true);
           //顺利获得name成员
          System. out.println("name=" +fieldName.get(new Person("likai","YongZhong" ,22,52)));
     }

21.成员变量反射的综合案例

     //3.成员变量的练习,将任意一个对象中的所有String类型的成员变量对应的字符串内容的"b"改为"a"
     public static void change(Object obj) throws Exception{
           Class clazz = obj.getClass();
           //其实只要成员变量不是private,就可以getFields(),而不必getDeclaredFields();
          Field[] fields = clazz.getFields();
           for(Field field: fields){
               ////getType标识了此 Field 对象所表示字段的声明类型,再判断
               if(field.getType() == String.class){
                   String str = (String) field.get(obj);
                   str = str.replace( 'b', 'a');
                   field.set(obj, str);
              }
          }
     }

22.成员方法的反射

     1.4 和 1.5 方法的invoke的区别

          JDK1.5 : public Object invoke(Object  obj, Object... args)

          JDK1.4 : public Object invoke(Object  obj, Object[] args)

          1.4 接受参数可以写成new Object[]{1,2,3};

 Class clazz = Class. forName("itcast.day1.Person");
          Person p = new Person("likai","YongZhong" ,22,52);
          
           //1.反射void showAge();
          Method method = clazz.getMethod("showAge");
          method. invoke(p);

23.对接收数组参数的成员方法进行反射

 //2.反射static void main( int i,String[] args ),静态方法第一个参数须为null
          Method method1 = clazz.getMethod( "main", int.class,String[].class) ;
           //采用(Object)new String[]{"123","345","567"}打包好.
          method1.invoke( null, 66,(Object)new String[]{"123","345" ,"567" });

     两种方法都不错,推荐第二种方法吧.     spacer.gif

24.数组与Object的关系及其反射类型

     所有具有相同元素类型和维数的数组都共享该 Class 实例对象.

     代表数组的Class实例对象的getSuperClass()方法返回父类为Object类对应的对象, 所以任意数组类型的父类都是Objec类.

  •      基本数据类型的一维数组可被当做Object类型使用,而不能当做Object[] 类型使用;

  •      非基本数据类型的一维数组,即可当做Object, 还可当做Object[]类型使用

     Arrays.asList()方法处理int[] 和 String[] 时的差异

          //int类型数组被当成[[I@11671b2]输出,但是String类型却[ aaa, bcd, kfc ]满意输出.
          System. out.println(Arrays.asList(a1));
          System. out.println(Arrays.asList(a4));

   注意到[[I@11671b2]输出,有两个[[,这说明包装成了二维数组.

25.数组的反射应用

     java.lang.reflect.Array类提供了动态创建和访问 Java 数组的方法。 

 //print任意Object,反射的应用使得处理array得心应手.
     public static void printObject(Object obj){
           if(obj.getClass().isArray()){
               int len = Array.getLength(obj);
               for(int i=0;i<len;i++){
                   System. out.print(Array.get(obj, i)+ " ");
              }                  
          }
           else{
              System. out.println(obj);
          }
     }

思考题: 怎么得到数组中的元素类型            

 //返回表示数组组件类型的 Class。如果此类不表示数组类,则此方法返回 null。
          System. out.println(arr.getClass().getComponentType());

得到某个元素具体的类型: 例如arr[5], 应该是arr[5].getClass().getName()吧.

26.ArrayList与HashSet的比较及HashCode分析

     ArrayList存储的是有序,可重复的元素

     HashSet存储的是无序,不可重复的元素,首先判断hasCode(),再判断equals(),只有两者都满足的时候才不存入,存入后一般不能修改这个对象的值, 因为一旦修改了后,会引起某些元素hashcode不等,这样就规避了一切使用hashCode方法的有效性,例如remove()就会变为无效,导致集合中元素无法从内存中删除,导致内存泄露.

wKioL1QEHPPyUt9xAAIcTU6Q9tk489.jpg

          Collection<Point> col = new HashSet<Point>();
          Point p1 = new Point(1,3);
          Point p2 = new Point(5,5);
          Point p3 = new Point(1,3);
          
          col.add(p1);
          col.add(p2);
          col.add(p3);

当重写hashCode()和equals()时,改变了判断条件,满足条件就相等不存,则输出的size为2.

否则只重写了一个或没有重写,系统判断都是不等的,都存入了,容易导致size较两个改写时增长.

27.框架的概念及用反射技术开发框架的原理

wKiom1QEG6biP_bPAANXj6SCOLw133.jpg

28.用类加载器的方式管理资源和配置文件

           //1. 使用InputStream, 这种相对路径相对于该项目. (Eclipse项目根目录)下开始寻找.
           in = new FileInputStream("src/itcast/day1/resource/config.properties");
          
           //2. 得到该类加载器从 classpath下 (即Eclipse下bin)读取指定的流,原因是类加载器就是从 classpath下开始寻找.(只用相对路径就够了)
           in = D8NewReflectTest2.class.getClassLoader().getResourceAsStream("itcast/day1/resource/config.properties");
     
           //3.1 Class类的getResourceAsStream方法也可 查找具有给定名称的资源。(相对时)class与 resourc/config.properties同级(相对目录)
           in = D8NewReflectTest2.class.getResourceAsStream("resource/config.properties");
           //3.2 Class类的getResourceAsStream方法也可 查找具有给定名称的资源。(绝对)绝对与 classpath,也就是bin下(绝对目录)       
          in = D8NewReflectTest2.class .getResourceAsStream ("/itcast/day1/resource/config.properties" );

29.由内省引出JavaBean的讲解(内省(IntroSpector)是Java语言对JavaBean 类属性、事件的一种缺省处理方法)

     与反射有关的一个知识:内省(IntroSpector)-->JavaBean

wKiom1QEG2Tw5rX3AAOiT004QI4924.jpg

30.对JavaBean的简单内省操作 

     public static void main(String[] args) throws Exception {
          XY pt1 = new XY(23,45);               
           //定义属性名x
          String propertyName1 = "x";
          
/*        //1. 设置x的值
          setMethodX(pt1,propertyName1,123);
          //2. 获取x的值
          System.out.println(getMethodX(pt1,propertyName1));

          //.................................

}
      //1. 设置x的值
     public static void setMethodX(XY pt1, String propertyName1,int x)
               throws IntrospectionException, IllegalAccessException,
              InvocationTargetException {
           //描述 JavaBean 通过一对存储器方法导出的一个属性, 参数: 参数名String + bean的Class
          PropertyDescriptor pd = new PropertyDescriptor(propertyName1,pt1.getClass());
           //获得应该用于读取属性值的方法。
          Method setMethod = pd.getWriteMethod();
          setMethod.invoke(pt1, x);
     }
      
      //2. 获取x的值
     public static Object getMethodX(XY pt1, String propertyName1)
               throws IntrospectionException, IllegalAccessException,
              InvocationTargetException {
           //描述 JavaBean 通过一对存储器方法导出的一个属性, 参数: 参数名String + bean的Class
          PropertyDescriptor pd = new PropertyDescriptor(propertyName1,pt1.getClass());
           //获得应该用于读取属性值的方法。
          Method getMethod = pd.getReadMethod();
           //得到get方法再调用
          Object retVal = getMethod.invoke(pt1);
           return retVal;
     }    

class XY{
     private int x ;
     private int y ;
     public XY(){}
     
     public XY( int x, int y){
           this.x = x;
           this.y = y;
     }
     public int getX() {
           return x ;
     }
     public void setX(int x) {
           this.x = x;
     }
     public int getY() {
           return y ;
     }
     public void setY(int y) {
           this.y = y;
     }
}

31.对JavaBean的复杂内省操作 

wKiom1QEGzHT7slOAAMRSzp_Bes986.jpg

      //3 用麻烦方法实现setX
     public static void method3(XY pt1, String propertyName1,int x) throws Exception{
           //在 Java Bean 上进行内省,了解其所有属性、公开的方法和事件
          BeanInfo info = Introspector.getBeanInfo(pt1.getClass());
          PropertyDescriptor[] pds = info.getPropertyDescriptors();
           for(PropertyDescriptor pd: pds){
               if(pd.getName().equals(propertyName1)){
                   Method method = pd.getWriteMethod();
                   method.invoke(pt1, x);  
                    return;
              }    
          }    
           //我知道该句写的不合理, 但还能接受.
           throw new RuntimeException("找不到对应方法");
     }

32.使用BeanUtils工具包操作JavaBean//nosuchelement?

     BeanUtils包和Logging包的导入.

          在项目下新建lib文件夹

          然后选中后 右键Build Path ,然后add to build path.

     BeanUtils常用方法(操作Map的方法就不在赘述)

          BeanUtil.sgetProperty(pt1, propertyName);

          BeanUtils.getProperty(pt1, propertyName, "20");

     其中接受的都是字符串,输出的也是字符串,做到了极大的通用性..

          BeanUtils.getProperty和setProperty中第二个参数可以做一级一级的操作,非常强大,例如 BeanUtils.setProperty(pt1, "birthday.time", "111");          

     当然也提供了PropertyUtils,提供了原样输出的功能,而不是通用的String输入输出.


你可能感兴趣的:(java,程序员,静态导入)