黑马程序员-java基础强化(一)

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

IDE Itegrity development environment 集成开发环境

在debug模式下,选中变量右键watch可以观察变量

 

静态导入:在用到静态方法是必须要写入类名,但是如果不想写入类名,则要使用静态导入

例 importstatic java.lang.Math.*;

注:jdk版本要1.5及以上

 

overload与override的区别

重载与复写

方法重载  子类继承父类

overload:方法名相同,但参数类型或者个数不同

override:父类的私有方法不能被覆写

 

可变参数

问题:一个方法接受的参数个数不固定,例如:

System.out.println(add(2,5,6));

System.out.println(add(1,5,9,6));

可变参数的特点:

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

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

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

public class VarableParameter {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

       // TODO Auto-generatedmethod stub

       System.out.println(add(2,5,9));

       System.out.println(add(8,9));

 

    }

    public static int add(int  ... args){

       int sum = 0;

       /*for(int i = 0; i< args.length; i++){

           sum += args[i];

       }*/

       for(int arg:args){

           sum += arg;

       }

       return sum;

    }

 

}

 

增强for循环

       语法:

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

       注意事项:

              迭代变量必须在()中定义!

              集合变量可以是数组或实现了Iterable接口的集合类

 

基本数据类型的自动拆箱与装箱

       自动装箱:Integer iObj = 3;

    自动拆箱:System.out.println(iObj + 3);

    基本数据类型的对象缓存:     Integer i1 = 12;

Integer i2 = 12;                     System.out.println(i1 == i2);

结果为true?

因为在-128~127之间会直接存入缓存,所以对象相同

 

享元模式:flyweight:有很多个小的对象,很多属性相同,把他们变成一个对象,不同的属性变成方法的参数称之为外部状态,相同的属性称之为内部状态

 

内部类是外部类的子类

 

类的方法可以返回自己这个类的类型

 

类里面可以定义静态常量,常量指向的结果就是自己这个类型的实例对象

 

枚举:

为什么要有枚举:

问题:定义一个表示星期几的类,可以用1~7表示周一到周日,但是有人用0那么这个类怎么表示…??

枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段就无法实现这一目标。

1.      枚举就相当于一个类,类中也可以定义构造方法、成员变量、普通方法和抽象方法。

2.      枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔。把枚举的成员方法或变量等放在枚举元素的前面,编译器报告错误。

3.      带构造方法的枚举

a)        构造方法必须定义成私有

b)       如果有多个构造方法,该如何选择哪个构造方法?参数…

c)       枚举元素MON和MON()的效果一样,都是调用默认的构造方法。

4.      带方法的参数

a)        定义枚举TrafficLamp

b)       实现普通next方法

c)       实现抽象next方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义。

d)       增加上表示时间的构造方法

5.      枚举只有一个成员时,就可以作为一种单例的实现方式。

    public enum TrafficLamp{

       RED(30){

 

           @Override

           public TrafficLamp nextLamp() {

              // TODO Auto-generatedmethod stub

              return GREEN;

           }

          

       },

       GREEN(45){

 

           @Override

           public TrafficLamp nextLamp() {

              // TODO Auto-generatedmethod stub

              return YELLOW;

           }

          

       },

       YELLOW(5){

 

           @Override

           public TrafficLamp nextLamp() {

              // TODO Auto-generatedmethod stub

              return RED;

           }

          

       };

       public abstract TrafficLamp nextLamp();

       private int time;

       private TrafficLamp(int time){

           this.time = time;

       }

      

    }

 

反射的基石àClass类

1.      Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class.

2.      对比提问:众多的人用一个什么类表示?众多的java类用一个什么类表示

a)        人àPerson

b)       Java类àClass

3.      对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个实例对象分别对应什么呢?

a)        对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码等等

b)       一个类被类加载器加载到内存中占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?Class

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

a)        类名.class,例如,System.class

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

c)       Class.forName(“类名”),例如,Class.forName(“java.util.Date”);

5.      九个预定义Class实例对象:

8个基本类型+void

Class.idPrimitive判断是不是基本类型

int.class ==Integer.TYPE

  Class.isArray判断是否为数组,总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void

例:

    public static void main(String[] args) throws Exception {

       // TODO Auto-generatedmethod stub

       String str1 = "abc";

       Class cls1 = str1.getClass();

       Class cls2 = String.class;

       Class cls3 = Class.forName("java.lang.String");

       System.out.println(cls1 == cls2);

       System.out.println(cls2 == cls3);

 

       System.out.println(cls1.isPrimitive());

       System.out.println(int.class.isPrimitive());

       System.out.println(int.class == Integer.class);

       System.out.println(int.class == Integer.TYPE);

       System.out.println(int[].class.isPrimitive());

       System.out.println(int[].class.isArray());

      

    }

反射:

1.      反射就是把java类中的各种成分映射成相应的java类。例如,一个java类中用一个class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等

2.      一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象后有什么用?怎么用?这是学习和应用反射的要点

Constructor

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

2.      得到某个类所有的构造方法:

例子:

Constructor[] constructors = Class.forName(“java.lang.String”).getConstructors();

3.      得到某一个构造方法:

Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);

//获得方法时要用到类型

4.      创建实例对象:

a)        通常方式:String str = new String(new StringBuffer(“abc”));

b)       反射方式:String str = (String)constructor.newInstance(new StringBuffer(“abc”));

//调用获得的方法时要用到上面相同类型的实例对象

5.      Class.newInstance()方法:

例子:String obj = (String)Class.forName(“java.lang.String”).newInstance();

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。

       //new String(newStringBuffer("abc"));

       Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

       String str2 = (String)constructor1.newInstance(/*abc*/new StringBuffer("abc"));//类型需要强制转换

       System.out.println(str2.charAt(2));

 

Field类

1.    Filed类代表某个类中的一个成员变量

2.    问题:得到的Filed对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢,所以字段fieldX代表的是x的定义,而不是具体的x变量。

 

示例:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“b”改为“a”

用Filed来调用成员变量

 

Method类

1. Method类代表某个类中的一个成员方法

2. 反射调用方式:System.out.println(charAt.invoke(str1,1));

如果传递给Method对象的invoke()方法的一个参数为null,这有什么意义呢?说明该Method对象对应的是一个静态方法...

3.  Jdk1.4和Jdk1.5的invoke方法的区别

Jdk1.5 public Object invoke(Object obj,Object...args)

Jdk1.4 public Object invoke(Object obj,Object[] args)即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用

 

用反射方式执行某个类中的main方法

1.    目标

a)      写一个程序,这个程序能够根据用户提供的类名,去执行类中的main方法

2.    问题

a)      启动java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按着那种语法进行处理呢?jdk1.5肯定要兼容参数。所以,在main方法传递参数时,不能使用代码

b)      MainMethod.invoke(null,new String[]{“xxx”}),javac只把它当做jdk1.4的语法进行理解,而不把它当做jdk1.5的语法解释,因此会出现参数类型不对的问题。

3.    解决办法:

a)      mainMethod.invoke(null,new Object[]{newString[]{“xxx”}});

b)      mainMethod.invoke(null,(Object)new String[]{“xxx”});编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

 

数组的反射

1.    具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

2.    代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。

3.    基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用

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

Array工具类用于对数组的反射操作

5.    思考:怎么得到数组中的元素:

没有办法直接得到,必须先得到数组中的元素,再getClass

例子如下:

public class ReflectTest {

 

    /**

     * @param args

     * @throws Exception

     */

    public static void main(String[] args) throws Exception {

       // TODO Auto-generatedmethod stub

       String str1 = "abc";

       Class cls1 = str1.getClass();

       Class cls2 = String.class;

       Class cls3 = Class.forName("java.lang.String");

       System.out.println(cls1 == cls2);

       System.out.println(cls2 == cls3);

 

       System.out.println(cls1.isPrimitive());

       System.out.println(int.class.isPrimitive());

       System.out.println(int.class == Integer.class);

       System.out.println(int.class == Integer.TYPE);

       System.out.println(int[].class.isPrimitive());

       System.out.println(int[].class.isArray());

      

       //new String(newStringBuffer("abc"));

       Constructor constructor1 = String.class.getConstructor(StringBuffer.class);

       String str2 = (String)constructor1.newInstance(/*abc*/new StringBuffer("abc"));//类型需要强制转换

       System.out.println(str2.charAt(2));

      

       ReflectPoint pt1 = new ReflectPoint(3, 5);

       Field fieldY = pt1.getClass().getField("y");

       System.out.println(fieldY.get(pt1));

       //公有的可以直接拿出来

       Field fieldX = pt1.getClass().getDeclaredField("x");

       fieldX.setAccessible(true);//暴力反射..

       System.out.println(fieldX.get(pt1));

       //私有的必须得用抢的了

      

       changeStringValue(pt1);

       System.out.println(pt1.toString());

 

       //str1.charAt(1);

       Method methodCharAt = String.class.getMethod("charAt", int.class);

       System.out.println(methodCharAt.invoke(str1, 1));

       System.out.println(methodCharAt.invoke(str1, new Object[]{2}));

 

       String startClassName = args[0];

       Method mainMethod = Class.forName(startClassName).getMethod("main", String[].class);

       //mainMethod.invoke(null, newObject[]{new String[]{"aaa","bbb","ccc"}});

       //上面一种将String类型又封装一次,使得多拆包一次将string数组作为参数

       mainMethod.invoke(null, (Object)new String[]{"aaa","bbb","ccc"});

       //上面这种直接将String强转为Object

      

       int[] a1 = new int[]{1,2,3};

       int[] a2 = new int[4];

       int[][] a3 = new int[2][3];

       String[] a4 = new String[]{"a","b","c"};

       System.out.println(a1.getClass() == a2.getClass());

       //System.out.println(a1.getClass()== a4.getClass());

       //System.out.println(a1.getClass()== a3.getClass());

       System.out.println(a1.getClass().getName());

       System.out.println(a1.getClass().getSuperclass().getName());

       System.out.println(a4.getClass().getSuperclass().getName());

      

       Object aObj1 = a1;

       Object aObj2 = a4;

       //Object[] aObj3 = a1;

       //基本类型不能转换成Object

       Object[] aObj4 = a3;

       Object[] aObj5 = a4;

      

       System.out.println(a1);

       System.out.println(a4);

       System.out.println(Arrays.asList(a1));

       System.out.println(Arrays.asList(a4));

      

       printObject(a4);

      

       printObject("xyz");

    }

 

 

    private static void printObject(Object obj) {

       Class clazz = obj.getClass();

       if(clazz.isArray() ){

           int len = Array.getLength(obj);

           for(int i = 0;i < len;i++){

              System.out.println(Array.get(obj,i));

           }

       }else{

           System.out.println(obj);

          

        }

      

    }

    private static void changeStringValue(Object obj) throws Exception{

       Field[] fields = obj.getClass().getFields();

       for(Field field:fields){

           if(field.getType() == String.class){

              //判断得到的是不是String类,字节码比较是否相同用==,值比较是否相同用equals

              String oldValue = (String)field.get(obj);

              String newValue = oldValue.replace("b", "a");

              field.set(obj, newValue);

           }

       }

      

    }

 

}

class TestArguments{

    public static void main(String[] args){

       for(String arg : args){

           System.out.println(arg);

       }

    }

}

被调用的类:

public class ReflectPoint {

    private Date birthday = new Date();

    private int x;

    public int y;

    public String str1 = "ball";

    public String str2 = "basketball";

    public String str3 = "hello";

   

    public ReflectPoint(int x, int y) {

       super();

       this.x = x;

       this.y = y;

    }

    public Date getBirthday() {

       return birthday;

    }

 

    public void setBirthday(Date birthday) {

       this.birthday = birthday;

    }

    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;

    }

    @Override

    public String toString() {

      

       return str1 + ":" + str2 + ":" + str3;

    }

    @Override

    public int hashCode() {

       final int prime = 31;

       int result = 1;

       result = prime * result + x;

       result = prime * result + y;

       return result;

    }

 

    @Override

    public boolean equals(Object obj) {

       if (this == obj)

           return true;

       if (obj == null)

           return false;

       if (getClass() != obj.getClass())

           return false;

       ReflectPoint other = (ReflectPoint) obj;

       if (x != other.x)

           return false;

       if (y != other.y)

           return false;

       return true;

    }

   

   

}

 

ArrayList与HashSet的比较及Hashcode分析

1.   ArrayList是有顺序的存储,当一个对象被存储两次时是可以的,因为有顺序所以是存储在不同地方的

2.   HashSet没有顺序,他要先判断要存储的对象是否已经存储在自己里,判断方式是通过HashCode

3.   当定义对象时对某些对象使用了hashCode和equals方法就表示如果再定义个相同的对象的话,他们的hashCode是相同的

反射的作用à实现框架功能

1.   框架与框架要解决的核心问题

我做房子卖给用户住,由用户自己安装门窗,我做的房子就是框架,用户需要使用我的框架,把门窗插入进我提供的框架中。框架与工具类的区别,工具类被用户的类调用,而框架则是调用用户提供的类

2.   框架要解决的核心问题

a)     先有框架,后才有用户写程序,哪框架程序怎样调用你写的类呢?

b)     因为在写程序是无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象,而要用反射的方式来做。

 

例子:

public class ReflectTest2 {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

       // TODO Auto-generatedmethod stub

       Collection collections = new HashSet();

       ReflectPoint pt1 = new ReflectPoint(3, 3);

       ReflectPoint pt2 = new ReflectPoint(5, 5);

       ReflectPoint pt3 = new ReflectPoint(3, 3);

       collections.add(pt1);

       collections.add(pt2);

       collections.add(pt3);

       collections.add(pt1);

      

       pt1.y = 7;

       collections.remove(pt1);

      

       System.out.println(collections.size());

    }

 

}

 

内省à了解javabean

1.    javabean是一种特殊的java类,主要用于传递信息,这种java类中的方法主要用于访问私有字段,且方法名符合某种命名规则。

2.    一个符合javaBean特点的类可以当作普通类一样进行使用,但把它当javabean用肯定需要带来一些额外的好处,我们才能了解和应用javabean

a) 在javaEE开发中,经常要使用到Javabean。很多环境就要求按javabean方式进行操作,别人都这么用和要求这么做,那你就没有挑选的余地!

b) JDK中提供了javabean进行操作的一些API,这套API就成为内省。

对于代码块进行方法抽取的方法:

用光标括住代码块,右键àRefactoràExtract Method

 

Beanutils工具包

1.    导入Beanutils工具包,将commons-beanutils放入工程中,右键Build PathàAdd to Path,发现会报错,需要commons-logging,用同样方式导入

2.    用Beautils类设定属性时,get属性返回的结果为字符串,set属性时可以接受任意类型的对象,通常使用字符串

3.    用Beautils类设定属性的优点:1.可以自动转换类型2.可以调用获得的属性的方法

 

例子:

public class IntroSpectorTest {

 

    /**

     * @param args

     */

    public static void main(String[] args) throws Exception{

       // TODO Auto-generatedmethod stub

       ReflectPoint pt1 = new ReflectPoint(3, 5);

      

       String propertyName = "x";

       PropertyDescriptor pd = getProperty(pt1, propertyName);

      

       Object value = 7;

       setProperties(pt1, pd, value);

      

       System.out.println(BeanUtils.getProperty(pt1,propertyName));

       BeanUtils.setProperty(pt1, propertyName, "9");

       System.out.println(pt1.getX());

/*    

 *      //java7的新特性

       Map map = {name:"zxx",age:10};

       BeanUtils.setProperty(map, "name", "lmh");

*/

       BeanUtils.setProperty(pt1, "birthday.time", "111");

       System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));

      

       PropertyUtils.setProperty(pt1, "x", 9);

       System.out.println(PropertyUtils.getProperty(pt1, "x").getClass());

    }

    private static void setProperties(Object pt1, PropertyDescriptor pd,

           Object value) throws IllegalAccessException,

           InvocationTargetException {

       Method methodSetX = pd.getWriteMethod();

       methodSetX.invoke(pt1, value);

    }

 

    private static PropertyDescriptor getProperty(Object pt1,

           String propertyName) throws IntrospectionException,

           IllegalAccessException, InvocationTargetException {

       PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());

       Method methodGetX = pd.getReadMethod();

       Object retVal = methodGetX.invoke(pt1);

       System.out.println(retVal);

       return pd;

    }

 

}

 

了解注解及java提供的几个基本注解

1.@SuppressWarning:提示过时方法不报异常

2.@Deprecated:提示这个方法过时

3.@Override:提示这是覆盖父类的方法,如果参数错误等,则会提示报错

总结:

注释相当于一种标记,在程序中加了注释就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无任何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法的参数以及局部变量上。

 

自动意注解及其应用

1.   在注解上加注解叫原注解,@Retention的三种取值SOURCE、CALSS、RUNTIME表示注解保留时间,分别对应java源文件àclass文件à内存中的字节码

2.   @Target则表示注释的位置如放在方法上就设置ElementType.METHOD等,若要放多个位置,则用数组形式表示

 

为注解增加基本属性

一个注解相当于一个胸牌,如果贴了,就是学生,否则就不是。如果相区分出是哪个班的,就要增加属性,也可以为注释增加注释

 

 

AnnotationTest类:

@ItcastAnnotation(annotationAttr = @MeatAnnotation("flx"),color = "red",value = "xyz",arrayAttr ={1,2,3})

public class AnnotationTest{

 

    /**

     * @param args

     */

    @SuppressWarnings("deprecation")

    @ItcastAnnotation("hello")

    public static void main(String[] args) {

       // TODO Auto-generatedmethod stub

       System.runFinalizersOnExit(true);

       if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){

           ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);

           System.out.println(annotation.color());

           System.out.println(annotation.value());

           System.out.println(annotation.arrayAttr().length);

           System.out.println(annotation.lamp().nextLamp().name());

           System.out.println(annotation.annotationAttr().value());

       }

    }

   

    @Deprecated

    public static void sayHello(){

       System.out.println("hi,美女");

    }

 

}

 

ItcastAnnotation注解:

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE,ElementType.METHOD})

public @interface ItcastAnnotation {

    String color() default "blue";

    String value();

    int[] arrayAttr() default {3,4,5,6};

    EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;

    MeatAnnotation annotationAttr() default @MeatAnnotation("lhm");

}

 

MeatAnnotation注解:

public @interface MeatAnnotation {

    String value();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值