------- http://www.itheima.comjava培训、android培训期待与您交流!-------
一、基础加强
1、Myeclipse和eclipse
1)Myeclipse:是elipse的插件,用于开发javaEE的平台,为其打补丁,扩展其功能,可以开发JavaEE程序即web项目,但是现在Myeclipse也集成了eclipse的功能,可直接使用Myeclipse。
2)eclipse:是开发java的一款专业的IDE(集成开发环境),以前需要Myeclipse才能开发JavaEE程序,现在的eclipse的版本也可以不用再安装Myeclipse插件,直接可以开发JavaEE项目。
2、Myeclipse介绍
(1)project(工程):一个工程包含有:包,jar包,资源文件,java源文件等内容。将一个工程的所有源文件用一个工程来组织,开发工具能对所有源文件集中管理,记住每个源文件的位置和相互关系,配置信息等都在工程中有记录。
(2)preferences(首选项):在workspace(工作间)中配置,将会影响到它下面所有的工程,一个工作间包含多个工程,不同透视图就是几个小窗口的集合。
(3)调试:设置断点,在行的开头双击即可。 运行程序,用debug as -- 程序
打开debug界面
(4)perspective(透视图)和view(视图)的关系:
view:每一个小窗口就是一个视图。可通过window下的show view调出相应的视图。
perspective:透视图就是若干个小窗口的集合。
(5)将其他工作间中的工程拷贝到当前工作间所在的文件夹下。在eclipse中右击工程--->导入--->浏览选择当前工作间目录下拷贝过来的工程。
(6)配置JDK环境:右击工程--->BuildPath --->Libraries(库)--->移除导入的工程的JDK库,增加自己的库。
注:Add JARs是增加打个Jar包,
如果Jar包不在当前工程文件夹中,用Add Exernd JARs
如果Jar包在当前工程文件夹中,用Add JARs
增加一个库相当于增加很多Jar,这是一个打包的过程。
3、静态导入
当类名重名时,需要指定具体的包名。
当方法重名时,指定具体所属的对象或者类。
import语句:是导入一个类或某个包中的所有类。
import static语句:导入一个类中的某个静态方法或所有静态方法。
可参见 黑马程序员---集合框架 七、
4、增强 for循环
增强for循环(高级for循环)其实就是for循环的简写形式。并不是所有的for循环都可以简写为foreach,高级for循环只适用于集合或数组的遍历操作。
高级for循环格式:
for(数据类型 变量名: 被遍历的集合或数组) {循环体}
在对集合或数组的操作中,集合一般的遍历方式是使用迭代器遍历,而且可以做删除操作,ListIterator在遍历时还可以进行增删改查操作,但如果用高级for循环,就不能做这些操作。
高级for循环的局限性: 只能获取集合元素,但不能对集合进行操作。
参见 可参见 黑马程序员---集合框架 七、
5、可变参数
简化代码、提高效率。
在定义可变参数时,一定要把参数定义在参数列表的最后面。如果定义在了开始或中间,虚拟机就会自动的将该参数后面的不同类型的参数纳入该参数列表
import java.util.*; class ParamDemo { public static void main(String[] args) { /* int[] arr = {1,25,7}; show(arr); */ show(1,2,4,23); } /* 当将方法定义为这中形式时,在主函数中调用该方法时, 要先新建一个数组对象,才能调用方法, 而将方法定义为这中形式,在调用该方法时,就不需要新建数组对象,直接调用方法即可 JDK1.5新特性:方法的可变参数 简化代码、提高效率 在定义可变参数时,一定要把参数定义在参数列表的最后面。 如果定义在了开始或中间,虚拟机就会自动的将该参数后面的不同类型的参数纳入该参数列表 */ public static void show(int... arr){ System.out.println(Arrays.toString(arr)); } /* 当将方法定义为这中形式时,在主函数中调用该方法时, 要先新建一个数组对象,才能调用方法 public static void show(int[] arr){ System.out.println(Arrays.toString(arr)); } */ }
6、基本数据类型的拆装箱
Integer x1= 4;
System.out.println(x1+2);
自动装箱:x1代表的是一个对象,是引用数据类型,由于自动装箱功能,x1可以直接这样写。
自动拆箱:x1+2 ,将类类型变量直接作为值进行运算。
7、享元模式
我们知道在word中可以输入任意的26个字母,这些字母可以说视为26个对象。但是这26个字母有很多相同的属性,而且每个对象都十分小,那么,这时就可以将这26个字母最为一个对象使用。除了相同属性之外的不同属性可以作为参数传递给对象。这种对很多很小的对象创建为一个对象的模式就叫做享元模式。
二、枚举
枚举是一个特殊的类,而且是一个不可被继承的final类,其中的元素都是类静态常量,它的出现可以将程序的错误在编译时期发现。
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器会报错。枚举可以让编译器在编译时既可以控制源程序中填写的非法值,普通的变量的方式在开发阶段无法实现这一目标。
用枚举类规定值,如WeekDay1类。以后用此类型定义的值只能是这个类中规定好的那些值,若不是这些值,编译器不会通过。
如果想在一个类中编写完每个枚举类和测试调用类,那么可将枚举类定义成调用类的内部类。
import java.util.Date; public class EnumTest { public static void main(String[] args) { // TODO Auto-generated method stub //1、赋的值只能在类WeekDay中定义好的某个常量 WeekDay1 weekDay = WeekDay1.MON; System.out.println(weekDay.nextDay());//SUN //2、当定义一个WeekDay枚举类后,只能调用规定的值 WeekDay weekDay2 = WeekDay.FRI; //自动将字符串打印 System.out.println(weekDay2); System.out.println(weekDay2.name()); //排行 System.out.println(weekDay2.ordinal()); //静态方法,传递一个字符串,可将该字符串转换为对应的 System.out.println(WeekDay.valueOf("SUN").toString()); //返回数组 System.out.println(WeekDay.values().length); //4、调用父类带参的构造方法 new Date(300){}; } //2、定义枚举(枚举的基本应用) public enum WeekDay{ //调用带参、无参的构造函数 SUN(1),MON(),TUE,WED,THI,FRI,SAT; //3、构造方法必须定义在元素列表之后,若元素后还有内容,则用; //构造方法必须私有修饰 //无参的构造函数 private WeekDay(){System.out.println("first");} private WeekDay(int day){System.out.println("second");} } //4、实现带有抽象方法的枚举 public enum TrafficLamp{ //RED元素{}都是TrafficLamp的每个实例对象 RED(30){ public TrafficLamp nextLamp(){ return GREEN; } }, GREEN(45){ public TrafficLamp nextLamp(){ return YELLOW; } }, YELLOW(5){ public TrafficLamp nextLamp(){ return RED; } }; //返回值类型仍为该类类型 public abstract TrafficLamp nextLamp(); private int time; //带参的构造函数 private TrafficLamp(int time){this.time = time;} } } WeekDay1.java public abstract class WeekDay1 { private WeekDay1(){} //常量 SUN是对象类型的值 public final static WeekDay1 SUN = new WeekDay1(){ //将抽象方法nextDay定义到每个SUN变量的内部 //这样就将大量的if else语句转移成了一个个独立的类 public WeekDay1 nextDay() { return MON; } /* * 采用抽象方法定义的nextDay可将大量的if else语句转换成了一个个独立的类。 public WeekDay1 nextDay() { if(this == SUN){ return MON; }else { return SUN; } //return MON; } */ //复写方法,将字符串打印 public String toString(){ return this == SUN?"SUN":"MON"; } }; //实现枚举的抽象方法 public final static WeekDay1 MON = new WeekDay1(){ public WeekDay1 nextDay() { // TODO Auto-generated method stub return SUN; } }; //带有抽象方法的枚举 public abstract WeekDay1 nextDay(); /* public WeekDay nextDay(){ if(this == SUN){ return MON; }else{ return SUN; } } */ public String toString(){ return this==SUN?"SUN":"MON"; } }
若枚举中只有一个成员时,可用单例模式实现(银行调度)。
三、反射
1、概述:
我们知道,用类来描述具有相同属性和行为的事物,而类的实例(也就是这类事物实实在在的个体)则是该类在现实世界中真实存在的对象。比如,用Person来描述人,而世界上的每个实实在在的个体就是Person的实例对象。
而,反射,简单地说,就是用来描述这些类中的成分的。用毕老师的话说,万物皆对象。而描述万物,就用类来描述,而这些类也有一些共性:比如说,这些类都依存在自己所属的包中,这些类也都有他们自己的类名、属性和方法;而对于任意一个对象,都可以调用它的任意一个方法和属性。
那么,如何获得这些类中的内容呢?
2、Class类
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
简单地说,Class类映射的是该对象所在的类(即该字节码对应的实例对象)。
我们一般描述类用关键字class来标识,如:
class Person{
。。。。。
//创建对象
Person p1 = new Person();
Person p2 = new Person();
}
那么,如何获得该字节码对应的实例对象呢?根据我们以往的思考方式,类可以用class来标识,那么Class类该怎么创建呢?
是这样吗?Class cls = new Class(); 其实,这样是不对的。虽然Class是一个类,但他有点特殊。Class类的作用主要是获得该字节码所属的实例对象。
获得各个字节码对应的实例对象的方式:
类名.class
对象.getClass();
Class.forName(“类名”); 这是一个静态方法,用于接收字符串类型的变量
还有TYPE 语法
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
下面举个例子:
用这三种方式验证”wangting”这个实例对象是否同属于一个字节码
//定义一个字符串对象 String str1 = "wangting"; Class cls1= String.class; Class cls2 = new String().getClass(); Class cls3 = Class.forName("java.lang.String"); System.out.println(cls1==cls2); //true System.out.println(cls1==cls3); //true 也可以通过Class类的isPrimitive方法判断该类是否是基本数据类型。 //是否是原始数据类型 System.out.println(cls1.isPrimitive());//false System.out.println(int.class.isPrimitive()); //true System.out.println(int.class == Integer.class); //false 基本数据类型和基本数据类型包装类 System.out.println(int.class==Integer.TYPE);//true System.out.println(int[].class.isPrimitive());//false //数组类型的Class实例对象 Class.isArray() //只要在源程序中出现的类型,都有各自的Class实例对象例如,int[]、void等 System.out.println(int[].class.isArray());
3、Constructor类
Constructor类是用来获得某类中的构造方法。当然,这是在使用字节码的前提下使用的。
//1、Constructor类(构造方法) System.out.println(new String(new StringBuffer("abc"))); //用反射的方法,实现new String(new StringBuffer("abc")); //使用Constructor的getConstructor方法 返回类型仍为Constructor Constructor cons =String.class.getConstructor(StringBuffer.class); //再通过newInstance创建对象 cons.newInstance(new StringBuffer("abc")); //abc //不能从Object类型转换为String类型 //String str = cons.newInstance(new StringBuffer("abc")); //所以要将新建对象强转 String str2 = (String)cons.newInstance(new StringBuffer("wangting")); //测试代码的功能是否实现,最简单的就是将结果打印看出现的问题。当然,实际开发不可打印 System.out.println(str2); //2、Class.newInstance(); 如何实现???? // String.class.getConstructor(StringBuffer.class).newInstance("wangshan"); // String str3 =(String)String.class.newInstance(new StringBuffer("wangshan"));
4、Field类
public class ReflectPoint { private int x; public int y; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } ReflectPoint rp = new ReflectPoint(3,5); //获得rp对象的字节码和ReflectPoint类上的字段。但这样并不能得到 Field fieldY = rp.getClass().getField("y"); System.out.println(fieldY.get(rp)); Field fieldX = rp.getClass().getField("x"); //因为x是私有的,所以报异常 //java.lang.NoSuchFieldException: x 没有找到这个字段 fieldX.setAccessible(true); System.out.println(fieldX.get(rp));
成员变量反射的综合案例:
ReflectPoint.java
public class ReflectPoint { private int x; public int y; public String str1 = "ball"; public String str2 = "baseketball"; public String str3 = "wangting"; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } //复写Object类中的toString方法 @Override public String toString(){ return str1+"---"+str2+"---"+str3; } }
ReflectTest.java
//综合案例: changeStringValue(rp); System.out.println(rp); public static void changeStringValue(Object obj) throws Exception{ //首先获得该类的字节码 文件,再获得该类中的字段 Field[] fields = obj.getClass().getFields(); for (Field field : fields){ //if (field.getType().equals(String.class)){} //一般比较字节码用== //如果传入的类型和该类型字节码恒等 if(field.getType() == String.class){ String oldValue = (String)field.get(obj); String newValue = oldValue.replace('b', 't'); field.set(obj, newValue); } } }
5、Method类
Method类表示的是类中的成员方法(字节码中的方法)。所以,先要获得字节码方法。
我们知道,不同的对象可以调用同一个类中的方法:
str1.charAt();
str2.charAt();
那么,如何使用反射做同样的操作呢?
String str1 = "wangting"; //一般方法调用charAt() System.out.println(str1.charAt(3)); //反射 //获得字节码方法,再用字节码方法调用getMethod方法,最后methodCharAt方法对象再调用invoke方法 Method methodCharAt = String.class.getMethod("charAt", int.class); //注意,字节码方法中都为字节码类型的参数列表 System.out.println(methodCharAt.invoke(str1, 3));
这是JDK1.5版本之后的新特性
6、用反射方式执行某个类中的main方法:
对接收数组参数的成员方法进行反射.
//TestArguments.main(new String[]{"111","222","333"}); String startingClassName = args[0]; Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); //mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}}); mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
7、数组与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()); //获得数组a1的字节码及名称 System.out.println(a1.getClass().getName()); //获得a1的字节码,并通过该字节码获得其父类字节码及名称 System.out.println(a1.getClass().getSuperclass().getName()); //获得a4的字节码,并通过该字节码获得其父类字节码及名称 System.out.println(a4.getClass().getSuperclass().getName()); //Objeect的反射 Object aObj1 = a1; Object aObj2 = a4; //Object[] aObj3 = a1; Object[] aObj4 = a3; Object[] aObj5 = a4; System.out.println(a1); System.out.println(a4); //将数组变成List集合 System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4)); printObject(a4); printObject("xyz");
8、ArrayList和HashSet比较
ArrayList集合的底层数据结构是数组结构,且是有序集合,每个元素有对应的索引(角标),如果两个元素相同,则按照顺序存入,
HashSet底层是哈希表结构,存入或取出没有顺序,如果存入的两个元素相同,先判断该元素的hashCode是否相同,若相同,则再比较两个元素是否是同一对象,若是,第二个元素不再存入。
四、JavaBean
JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。方法中不接收参数。
1、javaBean的属性:根据方法确定,这里属性是Age
如果第二个字母是小写的,则把第一个字母变成小写(去除get或set,剩下的是属性名)。如:
方法 属性名
gettime--->time
setTime--->time
getCPU--->CPU
如果要在两个模块之间传递多个信息,可以将这些信息封装到一个javaBean中,这种javaBean的实例对象通常称之为值对象(Value-Object)。这些信息在类中用私有字段来存储,如果速去或设置这些字段的值,则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢?javaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id,
2、对javaBean的内省操作
JDK中提供了对javaBean进行操作的API,这套API成为内省(IntroSpector)。
private static void setProperties(Object pt1, String propertyName, Object value) throws IntrospectionException, IllegalAccessException, InvocationTargetException { //1、属性描述符,接收属性名和所对应的自己吗,通过获得只读方法获取(返回值类型为Method) //再调用invoke方法 PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass()); Method methodSetX = pd2.getWriteMethod(); methodSetX.invoke(pt1,value); }
Map map = {name:"zxx",age:18};
BeanUtils.setProperty(map, "name", "lhm");
3、BeanUtils工具包操作javaBean:和上面的抽取的方法差不多,就是别人已经定义好了的内省方法。只需要导入别人的jar包使用就可以了。
五、注解
一个注解就是一个类(实例对象)。注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记。javac编译器,开发工具和其他程序 可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记, 就去干相应的事。
注意:标记可以加在包,类,字段,方法,方法的参数以及局部变量上,还可以加在注解上,这种注解为元注解。
@SuppressWarnings("deprecation"):压缩警告
@Deprecated :过时警告
@Override:重写方法注解
注解的定义格式:@ interface 注解名 {}
为注解添加属性:
为注解添加属性类似于为接口添加方法一样,例String color();这个语句就表示为注解添加一个字符串类型的属性color,那么在为别的类加上这个注解的时候就必须以@ 注解名(属性 = 值)的方式为每个属性赋值
属性的默认值:也可以在定义注解属性的时候就为这个属性设定一个默认值:String color() default "值";这样的话在添加注解的时候就可以不再指定这个属性的值,系统会自动将其设置为这个默认值;
value属性:当一个注解在被添加时只有一个名为value的属性需要设置值的时候就可以用@ 注解名(值)的方式直接填写值,而省略"value ="这一部分;
为注解添加其他高级属性:
数组属性:如int[] arrayAttr() default {1,2,3}; 如果数组属性的值只有一个元素,那么在赋值的时候可以省略大括号;即类似于@ 注解名(arrayAttr = 3)
枚举属性:如TrafficLamp lamp() default TrafficLamp.RED;
注解属性:如Annotation annotationAttr() default @ 注解名(属性名=属性值...)
六、泛型
JDK1.5版本以后出现新特性。用于解决安全问题,是一个类型安全机制。
1、ArrayList
整个称为ArrayList
ArrayList
整个ArrayList
ArrayList
ArrayList
2、ArrayList称为原始类型,
参数化类型与原始类型的兼容性:
(1)参数化类型可以引用一个原始类型的对象,编译报告警告,
Collection
(2)原始类型可以引用一个参数化类型的对象,编译报告警告。
Collection c = new Vector
(2)参数化类型不考虑类型参数的继承关系:
Vector