1 工具常用的快捷键 1) Eclipse和MyEclipse,IBM,2001,Java编写,开源,跨平台跨语言 2)Alt+/快速内容提示 3)Ctrl+1快速修补错误 4)Syso+Alt+/快速显示System.out.println()语句 5)Ctrl+Shift+F快速排版正确代码 6)Ctrl+Shift+X转大写,Ctrl+Shift+Y转小写 7)Ctrl+Shift+O一次性导入多个包 8)Ctrl+/加或减单行注释 9) Ctrl+Shift+/加多行注释,Ctrl+Shift+\取消多行注释 10) 选中行+Alt+上下光标键移动行 2 使用断点调试程序,使用Junit测试程序 1)通过断点方式调式程序的每个步骤 2)Step over查看代码粗粒度执行过程 3)Step into查看代码细粒度执行过程 4)@Before和@After会在@Test方法执行前后各执行一次 5)@BeforeClass和@AfterClass是在类前后各执行一次 *3 静态导入和自动装拆箱 1)静态导入可以导入对象,属性,方法,* 2)语法: import static java.lang.Math.PI; import static java.lang.Math.pow; import static java.lang.System.out; 3)在JDK5中,编译器自动将基本类型和对应的包装类型,自动转换 例如:int<->Integer *4 增强for循环 1)循环迭代数组/List/Set/Map集合
普通方法迭代for循环 | @Test public void test1(){ int[] is = {1,2,3,4,5}; for(int i=0;i<is.length;i++){ System.out.println(is[i]); } } | foreach增强for循环迭代数组 | @Test public void test2(){ int[] is = {1,2,3,4,5}; for(int value : is){ System.out.print(value+"\t"); } } | foreach增强for循环迭代list集合 | @Test public void testList(){ List<String> list = new ArrayList<String>(); list.add("jack"); list.add("marry"); list.add("sisi"); for(String name : list){ System.out.print(name+"\t"); } } | iterator方法环迭代set集合 | @Test public void testSet(){ Set<Integer> set = new HashSet<Integer>(); set.add(100); set.add(200); set.add(300); Iterator<Integer> it = set.iterator(); while(it.hasNext()){ Integer key = it.next(); System.out.print(key+"\t"); } } | | 2)对Map集合的二种迭代方式: a)keySet()
Map<Integer,String> map = new HashMap<Integer,String>(); map.put(100,"jack"); map.put(200,"marry"); map.put(300,"sisi"); Set<Integer> keySet = map.keySet(); Iterator<Integer> iterator = keySet.iterator(); while (iterator.hasNext()) { Integer key = iterator.next(); String value = map.get(key); System.out.println(key+"\t"+value); } | | b)entrySet()
Set<Entry<Integer,String>> entrySet = map.entrySet(); Iterator<Entry<Integer, String>> iterator = entrySet.iterator(); while (iterator.hasNext()) { Entry<Integer, String> entry = iterator.next(); Integer key = entry.getKey(); String value = entry.getValue(); System.out.println(key+"\t"+value); } | 3)在迭代集合时,一定要动态通知Iterator,而不要动态通知List集合,应选用ListIterator。
一、ListIterator有add()方法,可以向List中添加对象,而Iterator不能。 二、ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历。但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。 三、ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator 没有此功能。 四、都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。 ListIterator: 系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator 没有当前元素;它的光标位置 始终位于调用previous() 所返回的元素和调用 next() 所返回的元素之间。 | java.util 接口 ListIterator<E> |
方法摘要 | void | add(E e) 将指定的元素插入列表(可选操作)。 | boolean | hasNext() 以正向遍历列表时,如果列表迭代器有多个元素,则返回 true(换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true)。 | boolean | hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。 | E | next() 返回列表中的下一个元素。 | int | nextIndex() 返回对 next 的后续调用所返回元素的索引。 | E | previous() 返回列表中的前一个元素。 | int | previousIndex() 返回对 previous 的后续调用所返回元素的索引。 | void | remove() 从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。 | void | set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。 | | *5 可变参数 1)参数的个数不确定的 2)可变参数只能放置在参数的最后,即最右边 3)可变参数最少0个,最多1个 4)编译器将可变参数当作一个一维数组来对待
Java方法中的可变参数类型是一个非常重要的概念,有着非常广泛的应用。本文就以实例形式对此加以分析。具体如下: 一般来说,许多Java初学者在看到下面的这段代码的时候,都会问一个问题:dealArray方法里那三个小点点是什么啊? ?
1 2 3 4 5 6 7 8 9 | public class TestVarArgus { public static void dealArray(int... intArray){ } public static void main(String args[]){ } } | 这就是本文所要讨论的问题:可变的参数类型,也称为不定参数类型。英文缩写是varargus,还原一下就是variable argument type。通过它的名字可以很直接地看出来,这个方法在接收参数的时候,个数是不定的。那么好,现在就先来调用下这个方法。请看代码和输出: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class TestVarArgus { public static void dealArray(int... intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ dealArray(); dealArray(1); dealArray(1, 2, 3); } } | 输出: 1 1 2 3 通过main方法里的调用,可以看出来这个可变参数既可以是没有参数(空参数),也可以是不定长的。看到这里估计都能明白,这个不定长的参数其实和数组参数挺像的。事实上,也确实是这么回事儿。编译器会在悄悄地把这最后一个形参转化为一个数组形参,并在编译出的class文件里作上一个记号,表明这是个实参个数可变的方法。请看代码: ?
1 2 3 | dealArray(); //dealArray(int[] intArray{}); dealArray(1); //dealArray(int[] intArray{1}); dealArray(1, 2, 3); //dealArray(int[] intArray{1, 2, 3}); | 说到这里,那么可以来验证一下,看看是不是这个可变参数就是数组类参数?看代码: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class TestVarArgus { public static void dealArray(int... intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void dealArray(int[] intArray){//会有Duplicate method dealArray(int[]) in type TestVarArgus的错误 for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ dealArray(); dealArray(1); dealArray(1, 2, 3); } } | 从上面这段代码可以看出,这两个方法是冲突的,是无法重载的。到这里,再来做一个有意思的实验: 代码1: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class TestVarArgus { public static void dealArray(int... intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ int[] intArray = {1, 2, 3}; dealArray(intArray); //通过编译,正常运行 } } | 代码2: ?
1 2 3 4 5 6 7 8 9 10 11 12 | public class TestVarArgus { public static void dealArray(int[] intArray){ for (int i : intArray) System.out.print(i +" "); System.out.println(); } public static void main(String args[]){ dealArray(1, 2, 3); //编译错误 } } | 从上面这两段代码可以看出来,可变参数是兼容数组类参数的,但是数组类参数却无法兼容可变参数。其实对于第二段代码而言,编译器并不知道什么可变不可变,在它看来,需要定义一个dealArray(int, int, int)类的方法。所以,自然就无法去匹配数组类参数的dealArray方法了。 既然Java方法接收可变参数,那么接下来我们再来看一下下面的代码: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class TestVarArgus { public static void dealArray(int count, int... intArray){ } public static void dealArray(int... intArray, int count){//编译报错,可变参数类型应该作为参数列表的最后一项 } public static void main(String args[]){ } } | 这段代码说明了,可变参数类型必须作为参数列表的最后一项,而不能放在定长参数的前面。估计你会想到一个词“优先级”。因为没有确切的说明,只是这样一种规定,这里可以借用“优先级”这个词来理解一下,请看下面的代码: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class TestVarArgus { public static void dealArray(int... intArray){ System.out.println("1"); } public static void dealArray(int count, int count2){ System.out.println("2"); } public static void main(String args[]){ dealArray(1, 2); } } | 代码贴出来估计都知道是输出2,而不是1。这里需要记住:能匹配定长的方法,那么优先匹配该方法。含有不定参数的那个重载方法是最后被选中的。 最后,大家都知道main方法的参数就是一个数组类型的,那么它其实也是可以改成不定参数类型。试一试吧,看看有没有编译错误。 | *6 枚举 1)当取值是某范围中的之一,这时可以使用枚举 2)当向用户提示严重的错误时,尽可以使用抛异常的方式通知客户端 3)可以对枚举在运行时验证 4)可以对枚举在编译时验证 5)枚举值相当于实例变量 6)枚举类与普通一致,可以继承或实现,如果有抽像方法的话,可以利用每个枚举值以匿名内部类的方式去实现 7)枚举值可以用在switch()语句中 8)枚举类常用方法如下: a)name():显示枚举值 b)ordinal():显示枚举值对应的索引,从0开始 c)values():取得该枚举类对应的所有枚举值,是一个数组 d)valueOf():判段某个字符串是否属性枚举值之一
*7 反射总结 1)解析一个类的各个部分,形成一个个对象。 2)外存中的类,加载到内存中,会形成该对象的Class类,例如:String类,加载到内存中,就是StringClass对象。 3)使用不同的方式,取得同一个类型的字节码对象Class是相同的。 4)通过getXxxxx()只能取得该类public的类型 通过getDeclaredXxxxxx()可以取得该类非public的类型 设置非public类型的可访问性,默认为false,不可访问 c.setAccessible(true); 5)反射可以反射private/public的构造方法,字段,普通方法 6)在反射main方法时,编译器会将数组自动拆分,取第一个值 invoke第一个参数为null时,代表静态对象。 解决方案: //m.invoke(null,(Object)new String[]{"A","B","C","D"});,将数组当作对象,此时编译器不进行拆分 m.invoke(null,new Object[]{new String[]{"A1","B1","C1","D1"}});在数组中嵌入另一个数组
什么是反射? 反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。 反射用在哪里?框架 学习反射应该掌握些什么? | Class类 | Class类用于表示.class文件,画图演示一个对象的创建过程。 如何得到某个class文件对应的class对象。 类名.class 对象.getClass() Class.forName(“类名”)
//类名.class Class c1 = String.class; //对象.getClass() Class c2 = new String().getClass(); //Class.forName() Class c3 = Class.forName("java.lang.String"); if(c2==c3){ System.out.println("c2==c3"); }else{ System.out.println("c2!=c3"); } | //c2==c3 | //c1==c2 | 使用不同的方式,取得同一个类型的字节码对象Class是相同的。 | 总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int.class,int[].class,void.class… | 创建一个Person类 | public Person(){ System.out.println("public Person()"); } public void show(){ System.out.println("public void show()"); } | 取得person类的字节码对象 | Class clazz = Class.forName("cn.itcast.java.reflect.Person"); | //取得该类的唯一构造方法,空参构造方法,参数为null //Constructor c = clazz.getConstructor(null); | 创建实例 | Person p = (Person) c.newInstance(null); | 若person类的构造方法为 | public Person(String name,int age){ System.out.println("public Person(String name,int age)"); } | Constructor c = clazz.getConstructor(String.class,int.class); Person p = (Person) c.newInstance("berry",10); | 通过上述方法,构造实例 | private Person(){ System.out.println("private Person()"); } | //取得Person类对应的字节码对象Class Class clazz = Class.forName("cn.itcast.java.reflect.Person"); //取得该类的唯一构造方法 Constructor c = clazz.getDeclaredConstructor(null); //设置非public成员的访问性,默认false即不可访问性 c.setAccessible(true); Person p = (Person) c.newInstance(null); //执行方法 p.show(); | 获得公私有字段 | private String name; | Person p = new Person(); Class c = Class.forName("cn.itcast.java.reflect.Person"); Field f = c.getDeclaredField("name"); f.setAccessible(true); f.set(p,"杰克");//p.setName("杰克") System.out.println("用户名:" + p.getName()); | 用户名:杰克 | 获得公共字段 | public String name; | Class clazz = Class.forName("cn.itcast.java.mytest.Dog"); Dog dog = new Dog(); Field field = clazz.getField("name"); field.set(dog, "jack"); System.out.println(dog.getName()); | 反射普通方法 public void show() { System.out.println("public void show()"); } | Class clazz = Class.forName("cn.itcast.java.mytest.Dog"); Constructor constructor = clazz.getConstructor(null); Dog dog =(Dog) constructor.newInstance(null); Method method = clazz.getMethod("show", null); method.invoke(dog, null); | 带有参数的方法 | public void show(String name) { System.out.println("public void show()"+name); } | Class clazz = Class.forName("cn.itcast.java.mytest.Dog"); Constructor constructor = clazz.getConstructor(null); Dog dog =(Dog) constructor.newInstance(null); Method method = clazz.getMethod("show", String.class); method.invoke(dog, "jack"); | 带有参数的私有方法 | private void show(String name) { System.out.println("private void show()"+name); } | Class clazz = Class.forName("cn.itcast.java.mytest.Dog"); Constructor constructor = clazz.getConstructor(null); Dog dog =(Dog) constructor.newInstance(null); Method method = clazz.getDeclaredMethod("show", String.class); method.setAccessible(true); method.invoke(dog, "jack"); | 案例: | //加载属性文件,取得类名的方法名 Properties props = new Properties(); InputStream is = new FileInputStream("src/cn/itcast/java/reflect/class.properties"); props.load(is); String className = props.getProperty("className").trim(); String methodName = props.getProperty("methodName").trim(); //通过反射,执行该类的方法 Class c = Class.forName(className); Constructor con = c.getConstructor(null); Method m = c.getDeclaredMethod(methodName,null); m.setAccessible(true); m.invoke(con.newInstance(null),null); | |
单例设计模式 | 第一步:创建类 | public class Singeleton{} | 第二步:私有化构造方法 | private Singleton(){} | 第三步:声明一个私有的、静态的、本类私例变量 | private static Singleton instance; | 第四步:提供一个公共的静态方法,用来供外接访问和获得本类对象。方法内部创建一个本类对象,并返回 | public static Singleton getInstance(){ if(instance==null){ instance = new Singleton(); } return instance; } |
复制文件简单流程,回顾IO知识 | @Test public void test1() throws Exception { //创建输入流对象 InputStream is = new FileInputStream("C:\\d1.jpg"); //创建输出流对象 OutputStream out = new FileOutputStream("C:\\d1_copy.jpg"); int len = 0; byte[] buff = new byte[1024]; while ((len=is.read(buff))>0) { out.write(buff, 0, len);//写进输出对象 } is.close(); out.close(); } } | |