javaweb_day01

day1

总结:

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();

}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值