第1单元:Eclipse开发工具
eclipse及IDE开发工具介绍
MyEclipse是eclipse的一个插件,使得eclipse可以开发JavaEE项目
javaw.exe是启动java的图形界面所用的虚拟机
Java EE: Java Enterprise Edition
IDE: Integrated Development Environment
WorkSpace:工作间
工程管理与快捷键设置
设置整个工作间编译器版本和运行时环境的版本
window-->Preferences-->Java-->compiler或者installed JREs
切换workspace:File-->Switch Workspace,自命名一个workspace,没有则自动创建并打开一个工作间
perspective:透视图
每个java文件都要有一个包名,包名是公司的网址倒着写(去哪个公司面试包名就写哪个公司)
想要更改工程名,右键工程名选重构refactor-->rename。如果别的地方调用了这个类,类名也会跟着改,这就是重构的好处
为当前工作间下所有的工程设置快捷键
window-->preferences-->general-->Keys,输入content assist,选择unbind command解除原绑定,然后再设置新的快捷键,注意不要和其他快捷键冲突
查看工程所在目录:安装OperExplorer插件,点击Open Explorer图标即可
eclipse快捷键
提示快捷键:比如设置content assist:alt + / ,输入syso再按该快捷键就可以输出打印语句。注意:一般自动补全快捷键:word completion的快捷键默认也是alt+/,所以此时需要对其进行修改
Ctrl+z/y:取消/还原上次操作
Alt+↓: 移动当前行
Ctrl+Alt+↓: 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ :复制当前行到上一行(复制增加)
Ctrl+I :正确缩进代码
Ctrl+/ :单行注释
Ctrl+Shift+/ :多行注释
Ctrl+T:查看类或者接口的实现类
Alt+Shift+r :选中所有同一变量,方便进行批量修改
Alt+Shift+S/右键选Source-->Generate Constructor using Fields:Eclipse自动根据定义好的字段生成构造函数
直接复制源代码在某包下,自动生成相应文件!
视图管理与程序调试
一个透视图perspective就是若干个小窗口view的集合
如果关闭了一个view就点window-->show view来打开
调试一个变量debug步骤
- 在需要debug的代码前双击产生端点
- 点右键单击debug as进如debug透视图
- 鼠标选中一个变量,右键选watch就可以看到它的值
- 选择step over先前走一步观察变量的变化
配置eclipse的编译与运行环境
在eclipse中配置java模板代码
在eclipse中导入已有的工程
第2单元:java5的一些简单新特性
java5的静态导入与编译器语法设置
import static java.lang.Math.max;//注意不要写掉static
...
System.out.println(max(3,6));//省略调用类名
如果编译器的jdk版本低于1.5会报错!
Java5的可变参数与OverLoad与Override相关面试题
- 只能出现在参数列表的最后
- 三个点...位于变量类型和变量名中间,前后有无空格都可以
- 调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,该方法体中以数组的形式访问可变参数
public static int add(int x,int... args){
int sum = x;
/*for(int i=0;i<args.length;i++){
sum += args[i];
}*/
//for循环增强
for(int arg : args){
sum += arg;
}
return sum;
}
Java5的增强for循环
Java5的基本数据自动拆装箱及享元设计模式
第3单元:Java5的枚举
枚举的作用
用普通类模拟枚举的实现原理
- 私有的构造方法
- 每个元素分别用一个公有的静态成员变量来表示
- 可以有若干公有方法或者抽象方法,例如要提供nextDay()方法必须是抽象的
public abstract class WeekDay1 {
private WeekDay1(){}
public final static WeekDay1 SUN = new WeekDay1(){
public WeekDay1 nextDay() {
return MON;
}
};
public final static WeekDay1 MON = new WeekDay1(){
public WeekDay1 nextDay() {
return SUN;
}
};
public abstract WeekDay1 nextDay(); //采用抽象方法定义nextDay就将大量的if else语句转移成了一个个独立的类,这里在对象实例化时用匿名内部类来定义子类对象,public可以让子类实现该方法
/* public WeekDay nextDay(){
if(this == SUN){
return MON;
}else{
return SUN;
}
}
*/
public String toString(){
return this==SUN?"SUN":"MON";
}
}
枚举的基本应用
枚举是一种特殊的类,不用关键字class标识,而是通过关键字 enum来标识一个枚举类,每一个枚举元素都是该类的一个实例对象,例如可以调用WeekDay.SUN.getClass().getName()和WeekDay.class.getName();枚举类的方法
非静态方法:name,toString,ordinal
静态方法:values,valueOf
public static void main(String[] args) {
WeekDay weekDay2 = WeekDay.FRI;//访问枚举类中的元素
System.out.println(weekDay2);
System.out.println(weekDay2.name());//结果为FRI
System.out.println(weekDay2.ordinal()); //返回weekDay2的排序,此例为5,ordinal意思是序数
System.out.println(WeekDay.valueOf("SUN").toString());//将SUN字符串包装成一个WeekDay类型的枚举对象,等同于WeekDay.SUN
System.out.println(WeekDay.values().length); //values返回一个枚举类型数组
}
可以将枚举定义为内部类,此时:public enum WeekDay{SUN,MON,TUE,WED,THI,FRI,SAT//此后无语句,不需要加分号}}
实现带有构造方法的枚举
public enum WeekDay{
SUN(1),MON(),TUE,WED,THI,FRI,SAT;//在枚举元素后面跟上括号,表示创建该元素对应的实例对象时使用哪个构造方法,默认情况(即没有括号)是空参数的构造函数
private WeekDay(){System.out.println("first");}
private WeekDay(int day){System.out.println("second");}
}
一旦枚举中的元素被访问,所有的元素的构造函数都会被调用
public static void main(String[] args) {
WeekDay day2 = WeekDay.TUE;
}
运行结果
实现带有抽象方法的枚举
外部类可以有两个修饰符,一个默认的,一个publicpublic enum TrafficLamp{
//定义枚举的元素列表(在所有语句之前),并且调用父类的有参构造方法
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();//在父类中定义一个nextLamp的抽象方法,通过上面的匿名内部类来定义该方法的实现,public让子类可以实现该方法
private int time; //每种灯都有一个时间
private TrafficLamp(int time){this.time = time;}//时间通过构造方法传入,构造方法为private,代表只能在本类中使用
}
第4单元:Java1.2的反射
反射的基础_Class类
如何得到各个字节码对应的实例对象
- 类名.class,例如,Class cls1 = Date.class;
- 对象.getClass(),例如,new Date().getClass();
- Class.forName(完整的包名+类名),例如,Class.forName("java.lang.String"); 做反射时主要使用该方法,因为在写源程序的时候还不知道类名,需要作为参数传递。该方法会抛出异常ClassNotFoundException
九个预定义Class实例对象
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);//true,内存中只会有一份字节码文件
System.out.println(cls1 == cls3);//true
System.out.println(cls1.isPrimitive());//fasle
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class == Integer.class);//false
System.out.println(int.class == Integer.TYPE);//true,TYPE字段代表被包装的基本数据类型的字节码
System.out.println(int[].class.isPrimitive()); //false
System.out.println(int[].class.isArray());//true
总之,只要是在源程序中出现的类型,都有各自的class实例对象,例如int[],void
理解反射的概念
构造方法的反射
得到某个类所有的构造方法
得到某一个构造方法
创建实例对象
Class的newInstance()方法
成员变量的反射
public class ReflectPoint {
public int y;
private int x;
int z;
public ReflectPoint(int x, int y,int z) {
super();
this.x = x;
this.y = y;
this.z = z;
}
}
通过反射进行操作:
ReflectPoint pt1 = new ReflectPoint(3,5,2);
//被public修饰的变量,通过getField方法获取
Field fieldY = pt1.getClass().getField("y");//fieldY的值是多少?是5,错!fieldY不是对象身上的变量的值,而是类上定义的变量"y",要用它去取某个对象上对应的值
//在pt1对象身上拿到对应的变量的值,结果为3
System.out.println(fieldY.get(pt1));
//对于只要是在类中声明过的成员变量(包括public),都可以通过getDeclaredField方法获取
//被private修饰的变量,只能通过getDeclaredField方法获取(让该字段可见,但是还不能获取该字段的值)
Field fieldX = pt1.getClass().getDeclaredField("x");
//然后通过setAccessible将该变量的值设置为可以访问,也叫暴力反射(让该字段的值可以拿到)
fieldX.setAccessible(true);
//打印结果为5
System.out.println(fieldX.get(pt1));
//无访问修饰符的变量,只能通过getDeclaredField方法获取
Field fieldZ = rp.getClass().getDeclaredField("z");
//此时该变量的值即可访问,结果为2
System.out.println(fieldZ.get(rp));
成员变量反射的综合案例
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getDeclaredFields();
for(Field field : fields){
//if(field.getType().equals(String.class)){
if(field.getType() == String.class){ //字节码,也就是Class类的对象,用等号比较地址值,因为内存中都只有一份
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);//最后还要给对象中的成员变量赋值
}
}
}
成员方法的反射
得到类中的某一个方法
调用方法
- 通常方式:str.charAt(1);
- 反射方式:charAt.invoke(str,1); //str为调用该方法的对象,1为传入该方法的参数,invoke方法参考画圆的方法circle.draw(),画圆的参数是圆的私有属性,所以画圆的方法是属于圆的(专家模式)
jdk1.4和jdk1.5的invoke方法的区别
- jdk1.5: public Object invoke(Object