Bad version number in .class file
编译器的版本过高 运行环境版本过低
断点这一行的程序并未执行
断点:f5 : step into
f6 : step over
f7 : step return
drop to frame : 跳到当前方法的第一行
resume: 跳到下一个断点(如果没有下一个,则运行完整个程序)
watch: 观察变量或表达式的值
断点注意的问题:
1.断点调试完成后,要在breakpoints视图中清除所有断点
2.断点调试完成后,一定要记得结束运行断点的jvm. (两种方式)
常用的快捷键 :
设置的时候在 windows -à preferences à keys à 找到需要的快捷键 然后remove 修改 再binding
l 快捷键的配置,常用快捷键:
查看方法说明:F2
重置透视图 windows --- reset
更改为大写 Ctrl+Shift+X (常量要大写)
更改为小写 Ctrl+Shift+Y
复制行 Ctrl+Alt+向下键(有些不能用) 我的居然是Ctrl+Alt+向上键
Alt+向上键向下键 改变两行的顺序
查看类的继承关系 ctrl+T
查看源代码
1、ctrl+
2、ctrl+shift+T
ctrl+shift+L 查看所有快捷键
Junit测试工具 进行测试程序
JUnit是由Erich Gamma和Kent Beck编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承Test Case类,就可以用Junit进行自动测试
JUnit是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言)。它包括以下特性:
1、用于测试期望结果的断言(Assertion);
2、用于共享共同测试数据的测试工具;
3、用于方便的组织和运行测试的测试套件;
4、图形和文本的测试运行器。
测试流程:
1、扩展TestCase类;
2、覆盖runTest()方法(可选);
3、对应测试目标类书写testXXXXX()方法;
4、扩展TestSuite类,重载suite()方法,实现自定义的测试过程;
5、运行TestRunner进行测试
@Test 在每个方法上方都要写
@Before @ After 每个测试方法运行之前他们都运行运行
@BeforeClass 类加载的时候运行 (不常用)
private Person p;
@Before
public void before(){
System.out.println("before");
p = new Person();
}
@Test
public void testRun(){
p.run();
}
@Test
public void testEat(){
p.eat();
}
@After
public void after(){
System.out.println("after");
p = null;
}
结果 :
before
run!!
after
before
eat!!
After
private static Person p;
@BeforeClass
public static void before(){
System.out.println("before");
p = new Person();
}
@Test
public void testRun(){
p.run();
}
@Test
public void testEat(){
p.eat();
}
@AfterClass
public static void after(){
System.out.println("after");
p = null;
}
结果:
before
run!!
eat!!
after
常用的还是before after
Assert 断言 . 在方法体内写
是判断期望的值和实际的值是否相等 相等JUNIT就绿条否则就红条
总结: Junit主要运用在开发是测试每个小模块是否正常运行 不用注释其他程序 只需@Test每段小程序即可
Arrays 数组的帮助工具类 方法都是静态的 …
l Jdk5自动装箱/拆箱 只有1.5以后才有的
l 自动装箱:指开发人员可以把一个基本数据类型直接赋给对应的包装类。
l 自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型。
l 典型应用:
//1.5 jvm
Integer i = 1; //装箱
int j = i; //折箱
List list = new ArrayList();
list.add(1);
int j = (Integer)list.get(0);
Integer i = 1 ; // 装箱
Int j = I ; //拆箱
l 增强for循环
l 引入增强for循环的原因:在JDK5以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!
l JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组、或实现Iterable接口的集合类上。 看可以用否 就看它是否实现Iterable接口
l 语法格式:
for(变量类型 变量 :需迭代的数组或集合){
}
数组:
public void Testarr(){
int arr[] = {1,2,3};
for(int num : arr) {
System.out.println(num);
}
}
集合:
List:
public void test2(){
List list = new ArrayList();
list.add(1);
list.add(3);
list.add(5);
list.add(4);
list.add(2);
for(Object object : list) {
int i = (Integer)object;
System.out.println(i);
}
}
MAP:
Map map = new LinkedHashMap();
map.put("2", "meixi2");
map.put("3", "meixi3");
map.put("1", "meixi1");
/*传统方式1
Set set = map.keySet();
Iterator it = set.iterator();
while(it.hasNext()){
String key = (String) it.next();
String value = (String) map.get(key);
System.out.println(key +"=" + value );
}*/
// 增强for循环
for(Object object : map.keySet()){
String key = (String) object ;
String value = (String) map.get(key);
System.out.println(key +"=" + value );
}
LinkedHashMap 就有顺序了 做购物车的时候能够用到
public void test4(){
Map map = new LinkedHashMap();
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
/*传统方式2
Set set = map.entrySet();
Iterator it = set.iterator();
while (it.hasNext()){
Map.Entry entry = (Entry) it.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
System.out.println(key +"=" + value );
}*/
//增强for循环
for (Object obj : map.entrySet()) {
Map.Entry entry = (Entry) obj ;
String key = (String) entry.getKey();
String value = (String) entry.getValue();
System.out.println(key +"=" + value );
}
}
增强for 只适合取数据 不适合改 要修改 要用传统方式
l 可变参数 (就看出数组)
测试JDK中具有可变参数的类Arrays.asList()方法。分别传多个参、传数组,传数组又传参的情况。
从JDK 5开始, Java 允许为方法定义长度可变的参数。语法:
public void foo(int … args){
}
注意事项:
例子:
public void testSum(){
sum (1,2,3,4,5,6);
}
public void sum(int ...nums){
int sum = 0 ;
for (int i: nums){
sum += i;
}
System.out.println(sum);
}
可变参数需要注意的问题:public void aa(int ...nums,int x){这样不行
public void aa(int x,int ...nums) 这样可以 注意顺序
@Test
public void bb(){
List list = Arrays.asList("1","2","3");
System.out.println(list);
1 2 3
String arr[] = {"1","2","3","4"};
list = Arrays.asList(arr);
System.out.println(list);
1 2 3 4
int nums[] = {1,2,3,5}; //这个细节一定要小心 int 应该是Integer 接受的是对象 不能是数
list = Arrays.asList(nums);
System.out.println(list);
}
枚举 限定方法的取值 构造函数一定要私有化
l 为什么需要枚举?
l JDK 5新增的 enum 关键字用于定义一个枚举类。
l 枚举类具有如下特性:
l Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。常用方法:
枚举是限定某一个对象取值的
//枚举案例
public class Demo1 {
public void test(){
printGrade(Grade.A);
}
public void printGrade(Grade grade){ //A B C D E
}
@Test
public void test1(){
printGrade1(Grade1.D);
}
public void printGrade1(Grade1 grade){ //A B C D E
String value = grade.getValue();
System.out.println(value);
String localeValue = grade.toLocaleValue();
System.out.println(localeValue);
}
@Test
public void test2(){
printGender(Gender.MALE);
}
public void printGender(Gender gender){
}
}
//jdk5以前,自定义具有枚举功能的类
class Grade{
private Grade(){}
public static Grade A = new Grade();
public static Grade B = new Grade();
public static Grade C = new Grade();
public static Grade D = new Grade();
public static Grade E = new Grade();
}
//演示了如何定义枚举,以及如何使枚举的每一个对象,通过对象的属性和方法封装更多的信息
enum Grade1{ //class F A.toLocaleValue() "优"
A("100-90"){
public String toLocaleValue(){
return "优";
}
}
,B("89-80"){
public String toLocaleValue(){
return "良";
}
}
,C("79-70"){
public String toLocaleValue(){
return "中";
}
}
,D("69-60"){
public String toLocaleValue(){
return "一般";
}
}
,E("59-0"){
public String toLocaleValue(){
return "差";
}
}
; //object A:100-90 B:89-80 ....
private String value;
private Grade1(String value){
this.value = value;
}
public String getValue() {
return value;
}
public abstract String toLocaleValue();
}
枚举的信息
//得到所有值
Grade1 gs[] = Grade1.values();
for(Grade1 g : gs){
System.out.println(g.name());
}
//把字符串转成枚举(经常应用在数据校验上)
String value = "Y";
Grade1 g = Grade1.valueOf(value);
System.out.println(g.name());
}
//打印枚举的名称和位置
public static void get(Grade1 g){
String name = g.name();
System.out.println(name);
System.out.println(g.ordinal());
}
l 反射(做框架用的 )
l 一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。
反射:加载类,获得类的字节码
l Java中有一个Class类用于代表某一个类的字节码。
l Class类即然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName()。forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装
l 另外两种得到class对象的方式
l Class对象提供了如下常用方法:
Public Constructor getConstructor(Class<?>... parameterTypes)
Public Method getMethod(String name, Class<?>... parameterTypes)
Public Field getField(String name) public
public Constructor getDeclaredConstructor(Class... parameterTypes)
public Method getDeclaredMethod(String name,Class... parameterTypes)
public Field getDeclaredField(String name)
l 这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。解剖出的成员分别使用Constructor、 Method 、 Field 对象表示。
l Constructor类提供了如下方法,用于创建类的对象:
public Object newInstance(Object... initargs)
initargs用于指定构造函数接收的参数
l 多学一招:sun公司为简化开发人员创建对象,它在class对象中也提供了一个newInstance方法,用于创建类的对象。这样开发人员可以避免每次都需要去反射Constructor 类以创建对象。
//1.
Class clazz = Class.forName("cn.itcast.reflect.Person");
//2.
Class clazz1 = new Person().getClass();
//3.
Class clazz2 = Person.class;
反射类的构造函数
/反射类的构造函数,创建类的对象
public class Demo2 {
//反射构造函数:public Person(){
@Test
public void test1() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Constructor c = clazz.getConstructor(null);
Person p = (Person) c.newInstance(null);
System.out.println(p.name);
}
//反射构造函数:public Person(String name)
@Test
public void test2() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Constructor c = clazz.getConstructor(String.class);
Person p = (Person) c.newInstance("xxxxx");
System.out.println(p.name);
}
//public Person(String name,int password){
@Test
public void test3() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Constructor c = clazz.getConstructor(String.class,int.class);
Person p = (Person) c.newInstance("xxxx",12);
System.out.println(p.name);
}
//private Person(List list)
@Test
public void test4() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Constructor c = clazz.getDeclaredConstructor(List.class); //public
c.setAccessible(true); //暴力反射
Person p = (Person) c.newInstance(new ArrayList());
System.out.println(p.name);
}
//创建对象的别外一种途径:以下代码,等效于test1
@Test
public void test5() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Person p = (Person) clazz.newInstance();
System.out.println(p);
}
反射类的方法:
l Method对象提供了如下方法,用于执行它所代表的方法:
public Object invoke(Object obj,Object... args)
/反射类的方法:public void aa1(){
@Test
public void test1() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Object obj = clazz.newInstance();
Method method = clazz.getMethod("aa1",null); //wc
method.invoke(obj, null);
}
//反射类的方法:public void aa1(String name,int password){
@Test
public void test2() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("aa1", String.class,int.class);
method.invoke(p, "zxx",38);
}
//反射类的方法:public Class[] aa1(String name,int[] password){
@Test
public void test3() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("aa1",String.class,int[].class);
Class cs[] = (Class[]) method.invoke(p, "aaaa",new int[]{1,23});
System.out.println(cs[0]);
}
//反射类的方法: private void aa1(InputStream in){
@Test
public void test4() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getDeclaredMethod("aa1",InputStream.class);//private
method.setAccessible(true);
method.invoke(p,new FileInputStream("c:\\1.txt"));
}
//反射类的方法: public static void aa1(int num){
@Test
public void test5() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("aa1", int.class);
method.invoke(null, 23); //静态的 第一个参数就是null
}
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了
//反射类的方法: public static void main(String[] args)
@Test
public void test6() throws Exception{
Class clazz = Class.forName("cn.itcast.reflect.Person");
Method method = clazz.getMethod("main", String[].class);
//method.invoke(null, new Object[]{new String[]{"aa","bb"}}); //main(String s1,String s2) 因为他看到数组要拆开 就让他拆个够 所以再加上new Object[]
method.invoke(null, (Object)new String[]{"aa","bb"}); //main(String s1,String s2)
//jdk1.5 Method.invoke(String methodName,Object...args);
//jdk1.4 Method.invoke(String methodName,Object obj[]); a(String name,String password)
//jdk1.4 Method.invoke(String methodName,new Object[]{"aaa","123"});
}
Private 反射 c.setAccessible(true) 类外也可以访问
反射类的字段:
Field对象提供了如下方法,用于设置、获取对象属性的值:
public void set(Object obj,Object value)
public Object get(Object obj)
//反射字段
public class Demo5 {
//反射字段:public String name = "aaaa";
@Test
public void test1() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getField("name");
//获取字段的值
Object value = f.get(p);
//获取字段的类型
Class type = f.getType();
if(type.equals(String.class)){
String svalue = (String) value;
System.out.println(svalue);
}
//设置字段的值
f.set(p, "xxxxxxxxx");
System.out.println(p.name);
}
//反射字段:private int password;
@Test
public void test2() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getDeclaredField("password");//私有就declared
f.setAccessible(true);
System.out.println(f.get(p));
}
//反射字段:private static int age = 23;
@Test
public void test3() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
System.out.println(f.get(p));
}
=================================================================
l 内省(Introspector) 操作bean的属性的
l 为什么要学内省?
开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。
l 什么是Java对象的属性和属性的读写方法?
l 内省访问JavaBean属性的两种方式:
通过PropertyDescriptor类操作Bean的属性
通过Introspector类获得Bean对象的 BeanInfo,然后通BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
Javabean的属性个数看set或者get方法个数
//使用内省api操作bean的属性
public class Demo1 {
//得到bean的所有属性
@Test
public void test1() throws Exception{
BeanInfo info = Introspector.getBeanInfo(Person.class,Object.class); //得到bean自己的属性 去除掉后面的属性
PropertyDescriptor[] pds = info.getPropertyDescriptors();//属性描述器
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName());
}
}
//操纵bean的指定属性:age
@Test
public void test2() throws Exception{
Person p = new Person();
PropertyDescriptor pd = new PropertyDescriptor("age",Person.class);
//得到属性的写方法,为属性赋值
Method method = pd.getWriteMethod(); //public void setAge(int age) 个人理解就是得到写权限
method.invoke(p, 45);
//获取属性的值
method = pd.getReadMethod(); //public int getAge() 得到属性读权限
System.out.println(method.invoke(p, null));
}
//高级点的内容:获取当前操作的属性的类型
@Test
public void test3() throws Exception{
Person p = new Person();
PropertyDescriptor pd = new PropertyDescriptor("age",Person.class);
System.out.println(pd.getPropertyType());
}
=================================================================
l Sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils
l Beanutils工具包的常用类:
数据要先检查再使用
@Test
public void test1() throws IllegalAccessException, InvocationTargetException{
Person p = new Person();
BeanUtils.setProperty(p, "name", "xcc");
System.out.println(p.getName());
}
//下面的代码是有问题的,因为beanutils框架只支持基本数据类型的转换
@Test
public void test2() throws IllegalAccessException, InvocationTargetException{
String name = "aaaa";
String password = "123";
String age = "34";
String birthday = "1980-09-09";
Person p = new Person();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "age", age); //只支持8种基本数据类型
BeanUtils.setProperty(p, "birthday", birthday); //只支持8种基本数据类型
System.out.println(p.getName());
System.out.println(p.getPassword());
System.out.println(p.getAge());
System.out.println(p.getBirthday());
}
@Test
public void test3() throws IllegalAccessException, InvocationTargetException{
String name = "aaaa";
String password = "123";
String age = "34";
String birthday = "";
//为了让日期赋到bean的birthday属性上,我们给beanUtils注册一个日期转换器
ConvertUtils.register(new Converter(){
public Object convert(Class type, Object value) {
if(value==null){
return null;
}
if(!(value instanceof String)){
throw new ConversionException("只支持string类型的转换!!");
}
String str = (String) value;
if(str.trim().equals("")){
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e); //异常链不能断
}
}
}, Date.class);
Person p = new Person();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "age", age); //只支持8种基本数据类型
BeanUtils.setProperty(p, "birthday", birthday); //只支持8种基本数据类型
System.out.println(p.getName());
System.out.println(p.getPassword());
System.out.println(p.getAge());
System.out.println(p.getBirthday());
}
@Test
public void test4() throws IllegalAccessException, InvocationTargetException{
String name = "aaaa";
String password = "123";
String age = "34";
String birthday = "";
ConvertUtils.register(new DateLocaleConverter(), Date.class);
Person p = new Person();
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "password", password);
BeanUtils.setProperty(p, "age", age); //只支持8种基本数据类型
BeanUtils.setProperty(p, "birthday", birthday); //只支持8种基本数据类型
System.out.println(p.getName());
System.out.println(p.getPassword());
System.out.println(p.getAge());
System.out.println(p.getBirthday());
@Test
public void test5() throws IllegalAccessException, InvocationTargetException{
Map map = new HashMap();
map.put("name", "aaa");
map.put("password", "123");
map.put("age", "23");
map.put("birthday", "1980-09-09");
ConvertUtils.register(new DateLocaleConverter(), Date.class);
Person bean = new Person();
BeanUtils.populate(bean, map); //用map集合中的值,填充 bean的属性
System.out.println(bean.getName());
System.out.println(bean.getPassword());
System.out.println(bean.getAge());
System.out.println(bean.getBirthday());
}