您的位置:首页 > 职场人生

java程序员第七课 java基础加强

2015-11-17 16:50 323 查看
day07

1、上节内容回顾

2、java基础加强

myeclipse安装和使用

** 区分eclipse和myeclipse区别

1、eclipse是一个免费的开源的开发工具

2、myeclipse是一个收费的插件(破解版本)

** 如果创建项目

** 打开myeclipse时候,会创建一个工作空间: 工作空间的路径不能带中文 比如: F:\itcast\20150302

** 点击file-new-选择项目类型:比如Java Project

** 会有一个jdk环境,可以使用开发工具自带的jdk环境,也有可以使用自己本地安装的jdk
- 如何使用本地安装的jdk环境:


** 项目名、类名、方法名、变量的命名方式

- 包的名称方式:使用小写字母 比如 cn.itcast.test01

- 项目命名:使用小写字母名称 比如 day07

- 类命名:使用第一个字母要大写 如果有多个单词,每个单词的首字母大写 比如:TestUserName

- 方法命名: 方法名的首字母小写 如果有多个单词,从第二个单词开始首字母要大写 比如:userManager()

- 变量命名:变量名的首字母小写,如果有多个单词,从第二个单词开始首字母要大写 比如: String userName = “zhangsan”;

** 最基本原则:见名知意(看到这个名字能够看懂什么含义)

***  一定不要这样命名: yonghuManger   汉语拼音不要简写: rlgl


** 项目的运行方式:

* run as – java application

* dubug as – java application

debug调试模式(断点模式)

** 调试程序

1、设置一个断点 双击 这个时候程序运行到这一行时候,停止。

2、向下执行(单步执行) step over (F6)

3、resume F8:跳出当前的断点(如果后面有断点,会到这个断点,如果没有会结束程序)

** 查看源代码

1、step into F5: 进入到源代码里面

2、drop to frame:回到方法的顶端

3、step return F7: 从方法中跳出

** 去掉断点的方法

1、skip all breakPoints

2、remove all breakpoints

myeclipse快捷键

看文档

junit单元测试

单元测试:测试一个类,一个方法

引入junit支持的jar包,myeclipse中已经自带了这个jar包

入门

@Test

public void testSwim() {

TestJunit test1 = new TestJunit();

int a = 10/0;

test1.swim();

}

1、创建一个源代码文件夹 test

2、在这个test文件夹下 创建一个和要测试的类相同的包

3、使用注解方式 @Test来进行测试

* 测试方法的规范:必须是 public void 方法名() 现在使用junit4.x

*** 在junit3.x 时候命名 : public void 方法名() 方法名必须是 testXX开头


4、运行测试方法:

*run as - junit test

* 如果出现绿色的条,表示测试方法通过

* 直接在类中点击 run as - junit test 把所有可以运行的方法执行

@Test:这个方法可以进行单元测试

@Ignore:表示当前方法不做单元测试(不运行)

@After: 在方法之后 执行

@Before:在方法之前执行

@BeforeClass:在类加载之前执行 static方法 只会执行一次

@AfterClass:在类加载之后执行 static方法 只会执行一次

jdk5.0的一些新特性

jdk发展 1.1 1.2 1.4 jdk5.0

1、泛型(****

* 泛型经常使用在集合上 ,

* 如果集合没有使用泛型,向集合里面添加数据之后,数据失去了原有的类型,如果想要取数据,这个时候很容易出现

类型转换问题。

* 如果使用了泛型,可以定义这个集合里面的数据的类型,可以避免类型转换的问题

* 常用集合 List  Set  Map

** 在List上使用泛型
* List<String> list = new ArrayList<String>();
* list遍历方式有三种:普通for,增强for,迭代器

** 在set上使用泛型
* Set<String> set = new HashSet<String>();
* set遍历方式有两种:增强for,迭代器
* set和list区别(***)

** map上使用泛型
* Map<String,String> map = new HashMap<String,String>();
* map遍历方式,两种:
** 一种是获取所有key 根据key获取value
- //先获取所有的key
Set<String> set = map.keySet();
//遍历set
for (String key : set) {
//根据key获取value
String value = map.get(key);
System.out.println("key: "+key+" value:"+value);
}
** 第二种是获取key-value的关系
- //获取key - value关系
Set<Entry<String,String>> set1 = map.entrySet();
//遍历set1
for (Entry<String, String> entry : set1) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("key: "+key+" value:"+value);
}

* 泛形的基本术语,以ArrayList<E>为例:<>念着typeof
ArrayList<E>中的E称为类型参数变量
ArrayList<Integer>中的Integer称为实际类型参数
整个ArrayList<Integer>称为参数化类型ParameterizedType

* 泛型里面的类型只能是对象 对应八种基本数据类型的包装类和String

* 在方法上使用泛型
- 实现指定位置上数组元素的交换
- 实现逻辑相同,只是数据类型不同,这个时候使用泛型方法
- 定义方式:
/*
* 使用<T>  <A>   <B> :表示任意的类型
* 写在返回值之前
* 当在方法上定义了这个类型之后,这个类型就可以在方法中使用
* */
public static <T> void swap1(T[] arr,int i,int j) {
T temp = arr[i];  //temp == 20
arr[i] = arr[j];   // arr[i] == 40
arr[j] = temp;    // arr[j] == 20
}

* 作业 : 使用泛型方法实现: 任意类型的数组,颠倒数组中所有元素
比如: * Integer[] arr = {10,20};
result: 20,10
* String[] arr1 = {"aa","bb"};
result: "bb","aa"

* 在类上使用泛型
- public class TestDemo3<A> {

A aa;
public void test(A bb) {

}

public static <B> void test1(B cc) {

}}
- 在类上定义泛型,在类中都可以使用
*** 在静态方法中不能使用类上定义的泛型


2、枚举(了解)

** 在一定范围内取值,只能出现其中的一个 ,比如交通信号灯 有三种颜色 每次只亮其中的一个。

* 实现的发展历史:

* enum Color3 {

RED,GREEN,YELLOW;

}

* 构造方法有参数 在每个实例上加上参数

* 有抽象方法:在每个实例上实现抽象方法

*** 构造方法是私有的

* name() :返回枚举的名称
* ordinal() :枚举的下标
* valueOf(Class<T> enumType, String name):返回一个枚举对象

** 在类中没有,编译时候生成这两个方法
* valueof(String name)  转换枚举对象
* values()  获得所有枚举对象数组

** 对象、名称、下标这三个直接的互相转换


3、静态导入(鸡肋)

* 可以在类中导入一些静态的方法

* 导入方式 import static 包名.类名.静态属性|静态方法|

** import static java.util.Arrays.sort;

* 如果import static java.util.Arrays.toString时候,会出错,因为object里面也有toString

** 试用的场景:
- 比如实现一个计算器,计算器里面的方法都是Math里面的方法,这个时候可以使用静态导入


4、自动装箱/拆箱(**

* 装箱:把基本的数据类型封装成对象 (包装类)

* 拆箱:把包装类转换成基本数据类型

* Integer i = 1; //自动装箱
int m = i; //自动拆箱

* 在jdk1.4实现基本数据类型和包装类的转换
- Integer i = new Integer(1); //实现把基本数据类型转换成包装类
int m = i.intValue(); //实现把包装类转换成基本数据类型

* 常见的笔试题(向下兼容问题)
-   //在jdk5.0之前会执行doSomething(double i)这个方法,如果到了1.6,还会执行这个方法doSomething(double i)
public static void doSomething(double i) {
System.out.println("double.....");
}

public static void doSomething(Integer i) {
System.out.println("Integer.....");
}


5、增强for循环([b]****[/b])

* List set :可以使用增强for循环

map:不可以使用增强for循环

* 格式 for(数据类型 变量名称 : 要遍历的内容) {}

** 设计增强for循环的目的:为了取代迭代器

** 增强for循环的底层就是使用迭代器实现的

* 使用增强for循环的规则:必须实现Iterable接口的集合才可以使用增强for循环
- List  set之所以可以使用增强for循环,实现了Iterable接口
- map没有实现Iterable接口,所有不能使用增强for循环


6、可变参数(*

* 比如现在要实现两个数的相加,还要实现三个数的相加,这个时候变化只是参数的个数,这个时候可以可变参数

* 可以直接定义一个方法,实现这些操作

* 格式  数据类型...名称 比如 int...nums

*   public static void add1(int...nums) {  //nums是一个数组,有传递过来的所有参数
//System.out.println(nums.length);
int sum = 0;
//通过nums数组可以实现多个数的相加
for(int i=0;i<nums.length;i++) {
sum += nums[i];
}
System.out.println(sum);
}

* 定义规则:
1、一个方法里面只能有一个可变参数
- public static void add1(int...nums1,int...nums):这样是不可以的
2、可变参数必须放在方法的参数列表的最后
- public static void add1(int m,int...nums)

3、可变参数只能放在方法的参数列表中,不能单独定义变量


7、补充内容

* 泛型的擦除:定义这个泛型只是显示在源代码阶段,如果编译成class文件之后,泛型消失。

* 设计的目的:在程序的入口的时候,就规定一个类型

* 实现泛型方法,把数组中的元素颠倒
- //定义一个泛型方法
public static <T> void  reverse1(T[] arr) {
for(int i=0;i<arr.length/2;i++) {
T temp = arr[i];
arr[i] = arr[arr.length-i-1];
arr[arr.length-i-1] = temp;
}
}


7、反射([b]*****[/b]重点理解)

* 框架 底层都是使用反射来实现的。

* 一些通用性比较高的代码

* 画图分析原理

** 1、类要保存到本地硬盘 Person.java

2、编译成class文件 Person.class

3、使用类加载器把class文件加载到内存中,使用jvm操作

4、class文件在内存中的内容使用 Class类 进行表示
5、可以使用反射来获取类中的所有内容
- 属性,方法,构造(有参数和无参数的)(私有的属性和方法)
6、获取到Class类,有三种方式:
- 类名.class
- 对象.getClass()
- Class.forName("cn.itcast.servlet.TestServletDemo1");
* 属性使用 Field类表示
构造方法使用 Constructor类表示
方法使用 Method类表示

* Class类的api查看
- forName(String className) :参数是包类名称

- getConstructors() :返回所有的构造方法 返回 是一个 Constructor[]数组
- getConstructor(Class<?>... parameterTypes) :根据具体的参数返回相应的方法

- getDeclaredFields() :返回所有的属性 Field[]数组
- getDeclaredField(String name)  :参数是属性名称 返回 Field

- getMethods()  :返回所有的方法 返回数组 Method[]
- getMethod(String name, Class<?>... parameterTypes) :返回单一的方法
* 想要获取 setName(String name)
* getMethod("setName",String.class)

* 获取Class类
*       //类名.class
//      Class class1 = Person.class;
//      //使用对象获取
//      Class class2 = new Person().getClass();
//      //使用forname方法/day07/src/cn/itcast/test11/Person.java
//      Class class3 = Class.forName("cn.itcast.test11.Person");

* 操作构造方法
- 无参数的构造方法: Person p3 = (Person) class3.newInstance();
- 有参数的构造方法:
1、获取到有参数的构造方法
- Constructor constructor = class3.getConstructor(String.class,String.class);
2、获取实例
- Person p1 = (Person) constructor.newInstance("lisi","100");

* 操作属性
1、获取到要操作的属性
- Field field = class3.getDeclaredField("name");
2、设置属性的值
- field.set(实例对象, "wangwu");
*****  如何想要获取私有属性的时候 field.setAccessible(true);
3、获取值
- field.get(p3)

* 操作方法
1、获取到要操作的方法
- Method method = class3.getMethod("setName", String.class);
2、想要某个方法执行
- method.invoke(p3, "zhaoliu");
***** 想要访问私有的方法  method.setAccessible(true);

** 静态方法:  method.invoke(null, "zhaoliu");


package map;

import java.beans.BeanInfo;

import java.beans.IntrospectionException;

import java.beans.Introspector;

import java.beans.PropertyDescriptor;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.util.HashMap;

import java.util.Map;

import java.util.Map.Entry;

import java.util.Set;

import bean.Student;

/**

* map使用

* @author Administrator

* map的使用场景:存放的是键与值的映射 键 是唯一 值可以重复

* map缓存数据

* 1. 调用 Map 的 get() 方法获取数据;

如果返回不为 null, 直接返回该数据;

如果返回为 null, 则生成数据, 或者从其他地方获取数据, 然后存放入 Map 中, 最后返回该数据.

这里, 我们可以通过使用 Map 的containsKey() 方法来检测是否数据是否存在, 如果key存在, 则表明已经获取过一次数据, 那么直接返回该 key 在 Map 中的值. 不管是否为 null 都直接返回; 如果 key 不存在, 则去生成或者获取数据, 并放入到 Map 中, 并返回该数据.

这里使用 containsKey() 来检测可以应用于: 1. 从其他对方获取的数据可能为空, 并且不会有变化; 2. 获取数据比较耗时. 这个场景下, 使用该方法可以大大降低消耗, 特别是在同步情况下.

*/

public class Map01 {

public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("name", "q1");
map.put("age", "q2");
map.put("school", "q3");
//if(!map.containsKey("01")){

//}else{
//  System.out.println("当前已经存在");
//}
Student stu=new Student();
mapToBean(map,stu.getClass());
Student stu2=new Student();
stu2.setName("zhangsan");
stu2.setAge("18");
stu2.setSchool("bayixiaoxue");

Map<String,Object> map2 =beanToMap(stu2);

//遍历的方式
//1 Set 遍历方式
Set<String> keySet = map2.keySet();
for (String s : keySet) {
System.out.println(s+":"+map2.get(s));
}
//2Entry 遍历方式
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
//System.out.println(entry.getKey()+":"+entry.getValue());
}
}
/**
* bean 转换为map 反射
* @param value
* @return
*/
public static Map<String, Object> beanToMap(Object value) {
//if (value instanceof Map<?, ?>) {
//  return _resetMap(value);
//}
Map<String, Object> map = new HashMap<String, Object>();
if (value == null) {
return map;
}
Class<?> cls = value.getClass();
for (Field field : cls.getDeclaredFields()) {
try {
field.setAccessible(true);
map.put(field.getName(), field.get(value));
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
// 获取父类属性
Class<?> supcls = cls.getSuperclass();
for (Field field : supcls.ggetetDeclaredFields()) {
try {
field.setAccessible(true);
map.put(field.getName(), field.get(value));
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
/**
* map集合转bean 实体
* @param map
* @param type
*/
private static void mapToBean(Map<String, String> map,Class type) {
try {
//获取beaninfo 对象
BeanInfo beanInfo = Introspector.getBeanInfo(type);
//bean实体对象的属性数组
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
Object obj=type.newInstance();
for (int i = 0; i < propertyDescriptors.length; i++) {
PropertyDescriptor propertyDescriptor=propertyDescriptors[i];
//属性名称
String name = propertyDescriptor.getName();
if(map.containsKey(name)){
//给该对象对应的属性赋值
propertyDescriptor.getWriteMethod().invoke(obj, map.get(name));

}
}

Student s=(Student)obj;
System.out.println(s);
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // 获取类属性
catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


}

public class Hashtable

extends Dictionary

implements Map, Cloneable, java.io.Serializable

[java] view plaincopy

public class HashMap

extends AbstractMap

implements Map, Cloneable, Serializable

可见Hashtable 继承自 Dictiionary 而 HashMap继承自AbstractMap

Hashtable的put方法如下

[java] view plaincopy

public synchronized V put(K key, V value) { //###### 注意这里1

// Make sure the value is not null

if (value == null) { //###### 注意这里 2

throw new NullPointerException();

}

// Makes sure the key is not already in the hashtable.

Entry tab[] = table;

int hash = key.hashCode(); //###### 注意这里 3

int index = (hash & 0x7FFFFFFF) % tab.length;

for (Entry e = tab[index]; e != null; e = e.next) {

if ((e.hash == hash) && e.key.equals(key)) {

V old = e.value;

e.value = value;

return old;

}

}

modCount++;

if (count >= threshold) {

// Rehash the table if the threshold is exceeded

rehash();

tab = table;

index = (hash & 0x7FFFFFFF) % tab.length;

}

// Creates the new entry.

Entry e = tab[index];

tab[index] = new Entry(hash, key, value, e);

count++;

return null;

}

注意1 方法是同步的

注意2 方法不允许value==null

注意3 方法调用了key的hashCode方法,如果key==null,会抛出空指针异常 HashMap的put方法如下

[java] view plaincopy

public V put(K key, V value) { //###### 注意这里 1

if (key == null) //###### 注意这里 2

return putForNullKey(value);

int hash = hash(key.hashCode());

int i = indexFor(hash, table.length);

for (Entry e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

V oldValue = e.value;

e.value = value;

e.recordAccess(this);

return oldValue;

}

}

modCount++;

addEntry(hash, key, value, i); //###### 注意这里

return null;

}

注意1 方法是非同步的

注意2 方法允许key==null

注意3 方法并没有对value进行任何调用,所以允许为null

补充:

Hashtable 有一个 contains方法,容易引起误会,所以在HashMap里面已经去掉了

当然,2个类都用containsKey和containsValue方法。

HashMap                Hashtable


父类 AbstractMap Dictiionary

是否同步 否 是

k,v可否null 是 否

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,

主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。

HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。

Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步(Collections.synchronizedMap)。

Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

来源: /article/9810752.html

public class Hashtable

extends Dictionary

implements Map, Cloneable, java.io.Serializable

[java] view plaincopy

public class HashMap

extends AbstractMap

implements Map, Cloneable, Serializable

可见Hashtable 继承自 Dictiionary 而 HashMap继承自AbstractMap

Hashtable的put方法如下

[java] view plaincopy

public synchronized V put(K key, V value) { //###### 注意这里1

// Make sure the value is not null

if (value == null) { //###### 注意这里 2

throw new NullPointerException();

}

// Makes sure the key is not already in the hashtable.

Entry tab[] = table;

int hash = key.hashCode(); //###### 注意这里 3

int index = (hash & 0x7FFFFFFF) % tab.length;

for (Entry e = tab[index]; e != null; e = e.next) {

if ((e.hash == hash) && e.key.equals(key)) {

V old = e.value;

e.value = value;

return old;

}

}

modCount++;

if (count >= threshold) {

// Rehash the table if the threshold is exceeded

rehash();

tab = table;

index = (hash & 0x7FFFFFFF) % tab.length;

}

// Creates the new entry.

Entry e = tab[index];

tab[index] = new Entry(hash, key, value, e);

count++;

return null;

}

注意1 方法是同步的

注意2 方法不允许value==null

注意3 方法调用了key的hashCode方法,如果key==null,会抛出空指针异常 HashMap的put方法如下

[java] view plaincopy

public V put(K key, V value) { //###### 注意这里 1

if (key == null) //###### 注意这里 2

return putForNullKey(value);

int hash = hash(key.hashCode());

int i = indexFor(hash, table.length);

for (Entry e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

V oldValue = e.value;

e.value = value;

e.recordAccess(this);

return oldValue;

}

}

modCount++;

addEntry(hash, key, value, i); //###### 注意这里

return null;

}

注意1 方法是非同步的

注意2 方法允许key==null

注意3 方法并没有对value进行任何调用,所以允许为null

补充:

Hashtable 有一个 contains方法,容易引起误会,所以在HashMap里面已经去掉了

当然,2个类都用containsKey和containsValue方法。

HashMap                Hashtable


父类 AbstractMap Dictiionary

是否同步 否 是

k,v可否null 是 否

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,

主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。

HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。

Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步(Collections.synchronizedMap)。

Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: