----------------------------------debug------------------------------
可以在templates中配置模板
f5 step into跳入(进入方法里面)
f6 step over进过(一步一步走。)
f7 step return 跳出
drop to frame跳到当前方法的第一行代码,后退
resume跳到下一个断点执行,如果没有下一个段点,则执行完程序
watch 观察变量(或表达式)的值
------------------------------------------------------
String 是final型的 不能相加
静态代码快只执行一次(类加载时执行),比较两个对象是否为同一个字节码,可以使用==来比较(因为同一个字节码只有一份,如果相等则地址必须相同。
----------------------------junit------------------------------------
junit:运行这个类的全部的方法,点击类运行,
注解:
@Test:
写一个类,定义一个方法,该方法必须public,返回值为void,不能是static,
在方法上面加注解 @Test 按下Ctrl+1, 导入jar包,导包、
需要初始化
@BeforeClass static的 最先执行 1次
@Before 多少个方法执行多少次
代码
@After 多少个方法执行多少次
需要释放资源
@AfterClass static的 最后执行 1次
断言Assert.assertEquals("1", "1");期望的和返回的一样就是true,
-------------------------新特性jdk5.0---------------------------------------
自动装箱和拆箱:
基本类型->对象类型 比如 int ->Integer
自动拆箱 反之
int i = 1; //(对应Integer对象)
//装箱 i这么一个基本类型的数,可以赋值给Integer型的变量?因为java虚拟机自动取出i的值,放到Integer对象中,然后把对象给j。
Integer j = i;
//拆箱 怎么把对象赋给基本类型呢?因为自动取出对象的值,在赋给k(赋值的是对象封装的值)
int k = j;
-----------------------------------------------------------
可变参数
传入多个参数
List list = Arrays.asList("a","b","c","d");
System.out.println(list.size());
注意的问题:可变参数在传的时候可以直接传数组
String[] arr = new String[]{"a","b"};
List list = Arrays.asList(arr);
System.out.println(list.size());
//注意的问题:传基本数据类型数组时要千万小心,会当成一个对象传进去,打印的是地址,要是对象Integer
int arr[] = {1,2,3}; //Integer arr[] = {1,2,3};
list = Arrays.asList(arr);
System.out.println(list);
}
public static void sum(int ... nums){
//拿到可变参数,当成数组用即可
int sum = 0;
for(int num : nums){
sum += num;
}
System.out.println(sum);
}
-----------------------------------------------------------
增强for注意的问题:增强for只适合取数据,不要用它去修改数组或集合中的数据
//常见应用:集合
List list = new ArrayList();
list.add("a");//把1变成对象,add的是1对应的对象 装箱
list.add("b");
list.add("c");
Iterator it = list.iterator();
while(it.hasNext()){
int m = (String)it.next(); //拆箱
}
for(Iterator iter=list.iterator(); iter.hasNext(); ) {
String str = (String) iter.next();
System.out.println(str);
}
//增强for循环
for(Object obj : list) {
String str = (String) obj;
System.out.println(str);
}
-------------------------------------------------------------
增强for注意的问题:增强for只适合取数据,不要用它去修改数组或集合中的数据
迭代map
hashMap:无序
treeMap:传比较器,才有序麻烦
LinkedHashMap:有序~~~~~~~~~~~~~~~~~
Map m = new HashMap();
m.put("1", "aa");
m.put("2", "bb");
通过key得到value:
Set ks = m.keySet();
Iterator it = ks.iterator();
while (it.hasNext()) {//传统方式
String key = (String) it.next();
String value = (String) m.get(key);
System.out.println(key + "=" + value);
}
//for循环
for (Object obj : ks) {
String s = (String) obj;
String v = (String) m.get(s);
System.out.println(s + "=" + v);
}
通过Map.Entry得到键和值:超级重要 jstl也用这种方式
Set set = m.entrySet();
it = set.iterator();
while (it.hasNext()) {//传统方式
Map.Entry en = (Entry) it.next();
String key = (String) en.getKey();
String value = (String) en.getValue();
System.out.println(key + "=" + value);
}
//for循环
for (Object obj : m.entrySet()) {
Map.Entry me = (Entry) obj;
String key = (String) me.getKey();
String value = (String) me.getValue();
System.out.println(key + "=" + value);
}
---------------------------------------------------------------
反射:重要,用在框架上,反射的真个类
private:私有的外界无法访问到,但是反射能做到强行执行。不是public的都可以执行。Pubic也可以执行
装载类3种
//装载类1
Class clazz1 = Class.forName("cn.itcast.reflect.Person");
//2.
Class clazz2 = Person.class;
//3.
Class clazz3 = new Person().getClass();
反射构造方法//public Person(String name){}
Class clazz = Class.forName("cn.itcast.reflect.Person");
Constructor c = clazz.getConstructor(String.class);//类型来分辨
Person p = (Person) c.newInstance("xxx");//先调用构造函数
System.out.println(p.getName());
解剖私有//private Person(List list[]){}
Class clazz = Class.forName("cn.itcast.reflect.Person");
Constructor c = clazz.getDeclaredConstructor(List[].class);
c.setAccessible(true); //暴力反射
Person p = (Person) c.newInstance((Object)new ArrayList[4]);
System.out.println(p);
字段//设置name属性的值
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);
f.set(p, "xxx");
反射获取name属性的值
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getDeclaredField("name");
f.setAccessible(true);
String name = (String) f.get(p);
System.out.println(name);
方法//public void xx1()
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("xx1", null);
method.invoke(p, null);//调用方法运行:指定的方法p
private的//private int[] xx1(List list)
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getDeclaredMethod("xx1", List.class);
method.setAccessible(true);
int[] arr = (int[]) method.invoke(p, new ArrayList());
静态方法
main方法
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("main",String[].class);
//第一种method.invoke(null, new Object[]{new String[]{"1","2"}});
method.invoke(null, (Object)new String[]{"1","2"});
---------------------------------------------
内省:内省的是对象,操作反射bean的属性。框架用的
用途:页面注册、,经过框架,封装到bean里去,比如username,有这个字段就帮他封装到bean里去。
字段:name,age
属性:set和get方法
默认都有一个object的getClass()属性。因为都是它的子类有,会继承它。
introspector的API
getBeanInfo是封装bean的所有属性
getPropertyDescriptors()属性描述器的数组
getEeadMethod()读取
getWriteMethod()赋值
操作bean的属性
Student bean = new Student();
//得到bean的所有属性
BeanInfo info = Introspector.getBeanInfo(Student.class);
//得到bean的所有属性描述器
PropertyDescriptor pds[] = info.getPropertyDescriptors();
for(PropertyDescriptor pd : pds){ //name
String propertyName = pd.getName();
if(propertyName.equals("name")){
Method m = pd.getWriteMethod(); //setName(String name)
m.invoke(bean, "flx");
}
}
操作bean的指定属性: age
PropertyDescriptor pd = new PropertyDescriptor("age",bean.getClass());
Method method = pd.getWriteMethod(); //setAge(int age)
method.invoke(bean, 12);
//通过内省获取bean的age属性
method = pd.getReadMethod(); // getAge()
int age = (Integer) method.invoke(bean, null);
---------------------------------------------
beanUtils框架是Apache的
导入jar:最短的,
log4j:需要log4j的commons-logging.jar的支持
使用beanutils框架操作bean属性,会自动对数据进行转换,这仅于8种基本数据类型
基本操作
Student bean = new Student();
BeanUtils.setProperty(bean, "name", "flx");
String name = BeanUtils.getProperty(bean, "name");
较高级的操作
BeanUtils.setProperty(bean, "age", "12"); //beanutils框架会自动对数据进行转换,这仅于8种基本数据类型
System.out.println(bean.getAge()+1);
高级的操作
注册日期转换器ConvertUtils.register(new Converter(){
public Object convert(Class type, Object value) {
if(value==null){
return null;
}
if(!(value instanceof String)){
throw new ConversionException("只支持字符串的转换");
}
String date = (String) value;
if(date.trim().equals("")){
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(date);
} catch (ParseException e) {
throw new ConversionException(e);
}
}
},Date.class)
BeanUtils.setProperty(bean, "birthday", ""); //beanutils框架会自动对数据进行转换,(对象,属性名,属性值) //设置对象属性值
System.out.println(bean.getBirthday()); //date.toString()老外的格式
------------------------------------------------------
枚举:构造函数要private的。因为不能new
1.解决的问题,类的某个字段或方法传入的参数不能为任意值,必须为某一系列限定的取值
2. 解决问题的办法
办法1:在set方法中判断,如果不符合取值,抛一个运行时异常
public void setGrade(String grade) {
//加判断
if(!grade.matches("[ABCDE]")) {
throw new RuntimeException("参数非法");
}
this.grade = grade;
}
办法2:自定义一个Grade类,将构造方法私有,对外提供5个变量记住类的实例
public class Grade1 {
// 不让别人随便new对象
private Grade1() {}
//提供一组取值
public final static Grade1 A = new Grade1();
public final static Grade1 B = new Grade1();
public final static Grade1 C = new Grade1();
public final static Grade1 D = new Grade1();
public final static Grade1 E = new Grade1();
}
办法3:在jdk5中定义了枚举,用于解决这类问题
public enum Grade2 {
A,B,C,D,E;
}
3.所有的枚举都是Enum的子类,常用方法
Grade3 grade = Grade3.C;
// 获得枚举的名称
String name = grade.name();
System.out.println(name);
// 获得枚举的次序
int ordinal = grade.ordinal();
System.out.println(ordinal);
// 通过名字拿枚举对象
Grade3 g = Grade3.valueOf("D");
System.out.println(g.name());
// 获得所有的枚举
Grade3[] values = Grade3.values();
System.out.println(values[1].name());
4.枚举就是一个普通的java类,可以有方法、属性和构造方法
定义属性value记住枚举的值
public enum Grade4 {
A("90-100"),B("80-89"),C("70-79"),D("60-69"),E("0-59");
private String value;
private Grade4(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
定义方法toLocaleString返回中文格式
public enum Grade5 {
// 匿名内部类
A("90-100"){
public String toLocaleString() {
return "优";
}
}
,B("80-89"){
public String toLocaleString() {
return "良";
}
}
,C("70-79"){
public String toLocaleString() {
return "中";
}
}
,D("60-69"){
public String toLocaleString() {
return "差";
}
}
,E("0-59"){
public String toLocaleString() {
return "不及格";
}
};
private String value;
private Grade5(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
// 一个方法在没有想好怎么实现的时候,就声明为抽象方法,留给具体的子类去实现
public abstract String toLocaleString();
}
编写一个关于星期几的枚举WeekDay,设计一个方法返回中文格式的星期
MON("星期一"),TUE("星期二"),WED("星期一"),THU("星期一"),FRI("星期一"),SAT("星期一"),SUN("星期一");
private String value;
private WeekDay(String value){
this.value = value;
}
public String toLocaleString(){
return value;
}
-------------------------------------------------------
泛型:
1.泛型作用:提高容器的安全性,在编译阶段检查向集合中存储对象的类型。编译器在编译完带有泛型完成带有泛型的Java文件后,生成的class文件中将不再带有泛型信息,以保证程序的运行效率。
2. 好处:使用泛型的集合,在迭代的时候不用强转。将运行时可能发生的异常,转变为编译时错误。
3. 一旦使用泛型,两边的类型就必须一致,否则会出错。只在一边指定泛型不会报错。泛型的类型必须指定为引用数据类型,不能为基本数据类型
ArrayList<String> al = new ArrayList<Object>();
String str = al.get(1);
如果可以,明明集合里存的是Object,取出来的却都是String,不可能
ArrayList<Object> al = new ArrayList<String>();
al.add(new Student());
如果可以,明明集合只要String, 但是我们什么都能存,不可能
4. 为了向后兼容,可以只在一边指定泛型
ArrayList al = new ArrayList<String>();
相当于:
run(new ArrayList<String>());
public static void run(ArrayList al) {
}
---------------------------------------------
ArrayList<String> al = new ArrayList();
相当于:
doXX(new ArrayList());
public static void doXX(ArrayList<String> al) {
}
5. 自定义泛型
泛型必须先定义,再使用
泛型到底是什么类型,取决去调用者的指定
静态的变量不能使用泛型,因为人家会用类名.变量名的方式调用,没有机会指定泛型
方法中定义的泛型,必须在返回值前面先声明
泛型的定义决定了它作用范围内所有的该泛型类型的一致性
在类上定义泛型,作用与所有成员
public class Boy<T> {
private T t;
public void eat(T t) {
}
}
在方法上定义泛型,作用于当前方法
public <T> void play(T t) {
}
public static<T> void run(T t) {
}
类的静态属性不能使用泛型
private static T t1; //会报错,类名.变量名的方式调用,没有机会指定泛型