Java高新技术1(eclipse使用技巧,享元设计模式,枚举类型)
1.IDE概述:
1.IDE->integrated development environment(集成开发环境)
NetBeans: NetBeans包括开源的开发环境和应用平台 Jcreator
2.Ecliplse图形化界面->会使用javaw.exe启动
3.MyEclipse与Eclipse: MyEclipse扩展了Eclipse功能,是一个插件 Myeclipse的核心就是eclipse, 只不过Myeclipse在此基础上增加了许多的插件, 使用起来更加的方便 更详细了解两者区别于联系:http://www.cnblogs.com/panjun-Donet/articles/1156895.html
2.明确eclipse中的一些概念:
3.Eclipse
①工程(Project):
一般来说一个相对独立的项目就是一个工程,一个项目中
涉及的多个java文件,资源文件等用一个工程进行分类管理.
为什么要使用Project?在不使用工程管理的情况下,如果一个项目中包括多个java源文件, 编程人员需要精心维护这些源文件之间,以及源文件与其它文件的 目录关系,需要逐一编译这些源文件,需要手工启动运行编译后的结果 如果将一个程序的所有源文件用一个工程来组织,开发工具能对所有源文件集中 管理,记住每个源文件的位置和相互关系.工程中有哪几个源文件.启动类是哪个 启动参数设置等配置信息都在工程中都记录 之前一直在用cmd命令来compile,execute,那是因为同时操作的源文件,类等很少 还能手动管理,试想上千个呢? 如果不分类管理,那将是一件很痛苦的事. ②WorkSpace(工作空间/工作台) 一个workspace可以包含多个Project,一个workspace保留了eclipse的一套环境选项的配置 对工作间配置将影响其下的所有工程 例如:所使用的javac和java命令是哪个JDK版本里的等等. 如果要为eclipse再配置一套环境选项,可以在创建一个workspace 每个人都有自己的使用习惯(快捷键配置,窗体等等)形成自己的工作间 新建一个工作间:File->New->SwitchWorkspace->Other 新建的工作间是空的,没有任何工程
③工作集:(百度知道) 如果您有很多eclipse工程,举个例子来说: 您eclipse的workspace有10个工程,5个是A项目相关的, 5个是B项目相关的,如果10个工程都全部显示, 比较多,看着不方便,您就可以建一个working set, 对工程进行分组。您建一个working set A,把A相关的工程都加入到working set A, 再建一个woring set B,把B 相关的工程都加入到working set B。 这样的话您选择working set A的时候,就只显示A项目的工程, 选择working set B的时候,就只显示B项目的工程。
④新建项目->新建类(会同时生成.java和.class文件,两者名称相同) 字体看着很不爽调整代码的字体: 窗口(window)->首选项(Preference)->General(常规)->Appearance(外观)->Colors and Fonts(颜色和字体)->java编辑器文本字体
快捷键:
General下的Keys(键)进行相应调整
⑤透视图(PersPective)
就是不同的若干个小窗口(视图)的集合(Debug透视图等等)
3.配置eclipse编译与运行环境
1.配置编译环境和运行环境 窗口(window)->首选项(Preference)->java->编译器 ->已安装jre 进行相同JDK版本配置,也可以导入外部JDK 如果在运行一个工程下类文件发生: java.lang.UnsupportedClassVersionError:Bad version number in .classfile 例如:把1.7版本的javac.exe编译后的类文件用1.5的版本java.exe运行 高版本的java.exe可以运行低版本的javac.exe编译的程序 低版本的java.exe不可以运行高版本的javac.exe编译的程序 这也就是向下兼容 eclipse工作台(workspace)中的所有工程(project)继承工作台配置,其中某个工程可以覆盖工作台配置 java的继承和多态思想- -!!!2.模板(偷懒必备) 窗口(window)->首选项(Preference)->java->editor->templates3.在eclipse当前工作台中导入已有工程
①.把该project所在的文件夹拷贝到当前workspace下
②.project->import->General->Existing Projects into Workspace
4.build path
原文地址:http://blog.csdn.net/cheney521/article/details/8526414①source: source folder: 存放.java源文件的根目录; output folder: 源文件编译输出的存放.class文件的根目录; 纯“java project“中:一般把"src" 设置为source folder,把bin设置为output folder;
②Libraries:
是用来管理类库的,包括外部类库的添加和删除
很多的.class--打包->.jar---打包-->Libraries
可以Add External Jars,也可以Add Library-->User Library->New->根据自己需要,在自己的library增加.jar,该动作会影响当前工程的classpath
③Order and Export的up和down
调用优先级的问题,越在上边调用优先级越高,
例如:
在同包同类名的情况下,将优先从上到下执行搜索调用;
打勾与不打勾的区别在于导出jar包时是否将这个库的内容也打包到jar中,
勾为包含,不勾为不含。
4.享元设计模式(Flyweight Pattern):共享对象,节约内存
/* 享:共享 元:单元 举例装箱: -128~127这些数据太过于常用,也就是说经常在程序出现 如果我装箱,每个都new一个对象,相当浪费内存 因此可以这样干: 内部建立一个长度为256的引用数组,数组中的每个引用变量指向一个 Integer对象(-128~127),当装箱时,检查是否在-128~127范围内,是 使用cache数组中的对象. */
5.枚举类型
1.枚举概述:
/* 枚举:一一列举 说明为有穷个,可以列举出来.例如:工作日(周日~周六),颜色(红,黄,.....),字体大小(1,2..) 为什么要有枚举? 问题:要定义星期几或性别的变量,该怎么定义?假设用1~7分别表示星期一到星期日, 但有人会写成int weekday=0,也就是说不统一; 枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错(一种约束/限定) 枚举优点: 枚举可以让编译器在编译时就可以控制源程序中填写的非法值 普通变量的方式在开发阶段无法实现这一目标 */2.用普通类模拟枚举功能:
class WeekDay{ private WeekDay(){}//不允许外部new对象,只能使用我内部提供的 public static final WeekDay SUN=new WeekDay();//外部不能创建对象那只能定义成static public static final WeekDay MON=new WeekDay(); public static final WeekDay TUES=new WeekDay();//这里为了简化代码,只到星期二 public String toString(){//为了打印结果的友好 return this==SUN ? "星期日" :(this==MON ? "星期一" : "星期二"); } public static void main(String[] args){ WeekDay wd=WeekDay.TUES;//你只能取MON,SUN,TUES其它不能取,否则编译期不能通过 System.out.println(wd);//星期二 } }3.对于以上添加nextDay方法:
class WeekDay{ private WeekDay(){}//不允许外部new对象,只能使用我内部提供的 public static final WeekDay SUN=new WeekDay();//外部不能创建对象那只能定义成static public static final WeekDay MON=new WeekDay(); public static final WeekDay TUES=new WeekDay();//这里为了简化代码,只到星期二 public WeekDay nextDay(){ return this==SUN ? MON :(this==MON ? TUES :SUN);//让TUES的next为SUN } public String toString(){//为了打印结果的友好 return this==SUN ? "星期日" :(this==MON ? "星期一" : "星期二"); } public static void main(String[] args){ WeekDay wd=WeekDay.TUES;//你只能取MON,SUN,TUES其它不能取,否则编译期不能通过 System.out.println(wd);//星期二 } }4.采用匿名内部类的形式完成nextDay功能(多态)
abstract class WeekDay{//原类为抽象,也不能创建对象private WeekDay(){} public static final WeekDay SUN=new WeekDay(){ public WeekDay nextDay(){ return MON;//MON为静态随着类的加载而加载 } }; public static final WeekDay MON=new WeekDay(){ public WeekDay nextDay(){ return TUES;//MON为静态随着类的加载而加载 } }; public static final WeekDay TUES=new WeekDay(){ public WeekDay nextDay(){ return SUN;//MON为静态随着类的加载而加载 } }; public String toString(){ return this==SUN ? "星期日" :(this==MON ? "星期一" : "星期二"); }public abstract WeekDay nextDay();
public static void main(String[] args){
WeekDay wd=WeekDay.TUES;
System.out.println(wd);
System.out.println(wd.nextDay());
}
}
/*
该思想很好的把nextDay中的判断融入到了匿名子类对象中,省去繁琐的判断
*/
6.深入Java枚举:主要参考博文:http://www.cnblogs.com/frankliiu-java/archive/2010/12/07/1898721.html
1.java中枚举的定义:
enum Colour{ //短小精悍 RED,BLUE; } /* java语言规范中枚举的格式: An enum declaration has the form: EnumDeclaration: ClassModifiersopt enum Identifier Interfacesopt EnumBody EnumBody: { EnumConstantsopt ,opt EnumBodyDeclarationsopt } */通过反编译看看编译器对这孩纸干了什么:
//反编译后: final class Colour extends java.lang.Enum<Colour> {//继承了Enum,因此可以使用其中一些方法 public static final Colour RED; public static final Colour BLUE; /*内部定义了values和ValueOf方法*/ public static Colour[] values(); Code: 0: getstatic #1 // Field $VALUES:[LColour; 3: invokevirtual #2 // Method "[LColour;".clone:()Ljava/ lang/Object; 6: checkcast #3 // class "[LColour;" 9: areturn public static Colour valueOf(java.lang.String); Code: 0: ldc_w #4 // class Colour 3: aload_0 4: invokestatic #5 // Method java/lang/Enum.valueOf:(Lj ava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; 7: checkcast #4 // class Colour 10: areturn /*静态代码块中执行的内容*/ static {}; Code: /* 下面几句相当于干了这些事:Colour RED=new Colour("RED",0);
Colour BLUE=new Colour("BLUE",1); 在Colour构造函数中使用(super("RED",0);)了父类的构造函数: protected Enum(String name,int ordinal) name - - 此枚举常量的名称,它是用来声明该常量的标识符。 ordinal - - 枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。 */ 0: new #4 // class Colour 3: dup 4: ldc #7 // String RED 6: iconst_0 7: invokespecial #8 // Method "<init>":(Ljava/lang/Strin g;I)V 10: putstatic #9 // Field RED:LColour; 13: new #4 // class Colour 16: dup 17: ldc #10 // String BLUE 19: iconst_1 20: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V 23: putstatic #11 // Field BLUE:LColour; /*创建一个数组对象相当于:new Colour[2]*/ 26: iconst_2 27: anewarray #4 // class Colour /*将RED和BULE存入到创建的数组中,其实就是数组中的引用变量分别指向这两个对象*/ 30: dup 31: iconst_0 32: getstatic #9 // Field RED:LColour; 35: aastore 36: dup 37: iconst_1 38: getstatic #11 // Field BLUE:LColour; 41: aastore 42: putstatic #1 // Field $VALUES:[LColour; 45: return }/* enum Colour被解释成: final class Colour extends java.lang.Enum<Colour> 自定义的枚举类会继承Enum中的方法 public static final Colour RED; public static final Colour BLUE; 原来枚举中定义的是引用类型->和刚才的自定义类中的成员如出一辙 public static Colour[] values(); 静态方法,返回一个包含全部枚举值的数组 public static Colour valueOf(java.lang.String); 内部调用了继承的valueOf(Class,String)方法,返回 返回带指定名称的指定枚举类型的枚举常量。 名称必须与在此类型中声明枚举常量所用的标识符完全匹配。(在这里只能传入"RED"和"BLUE") (不允许使用额外的空白字符。) 好啊,书写的挺简单,其实编译器帮你干了好多事,不用自己去自定义枚举,简化了书写 */2.枚举中的构造方法:
enum Colour{ RED,BLUE(2);//必须位于所有成员之前,其实RED相当于RED(),BLUE(2)会调用构造方法Colour(int x) private Colour(){} private Colour(int x){ System.out.println("x="+x); } }import static java.util.Arrays.toString;//该语句只导入了Arrays中的toString方法,因此下面还需要导入Arrays类 import java.util.Arrays; public class EnumTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(WeekDay.TUES.nextDay()); Colour c=Colour.RED; System.out.println(c.toString()); System.out.println(Colour.valueOf("BLUE"));//返回一个Colour对象 System.out.println(Arrays.toString(Colour.values())); } }enum Colour{ RED,BLUE(2); private Colour(){} private Colour(int x){} } //反编译看出其调用方式: 21: invokespecial #11 // Method "<init>":(Ljava/lang/String;II)V //相当于调用了private Colour(Stirng ,int ,int) //一个int值代表枚举元素的序号,另一个就是x值3.带有抽象方法的枚举:枚举其实就是一个final class,其中可以有抽象方法
/*带有抽象方法的枚举*/ enum TrafficLamp{//enum前面不能用abstact修饰 RED(4){ public TrafficLamp nextLamp(){ return GREEN; } }, /* 相当于 public static final RED=new TrafficLamp("RED",0,4){ public TrafficLamp nextLamp(){ return GREEN; } }; 枚举中的匿名子类对象 ,这一点我们可以从编译后的class文件中看出: TrafficLamp$1.class TrafficLamp$2.class TrafficLamp$3.class */ YELLOW(2){ public TrafficLamp nextLamp(){ return RED; } }, GREEN(5){ public TrafficLamp nextLamp(){ return YELLOW; } }; private int time;//设置一个灯亮的时间 private TrafficLamp(){} private TrafficLamp(int time){ this.time=time; } public abstract TrafficLamp nextLamp();//父类的抽象方法}枚举中一旦有有抽象方法,每个元素都必须实现该方法. 因为: 一旦含有抽象方法,TrafficLamp为abstract class,本身不能new对象,只能通过子类来new对象 那么枚举中的每个元素必须采用匿名内部类的方式实现该抽象方法. 含有抽象方法的枚举会被编译器解释为: abstract class TrafficLamp extends java.lang.Enum<TrafficLamp>4.枚举与单例
//枚举只有一个成员(相当于只有一个对象),就可以做为一种单例的实现方式.
/*单例设计模式*/
enum SingleInstance{
REF;
}5.最后一点枚举类型可以在switch(枚举类型) 中使用(套用原作者):
/* 回想Switch(变量) :该变量的类型可以是::byte ,short,char,int,以及JDK 1.7最新特性添加一个String 现在多了个枚举类型 */ Colour c=Colour.RED; switch(c){ case RED:System.out.println("红色");break;//这里的case后面的常量简写为RED,而没有写Colour.RED,说明编译器根据c推断枚举常量类型 case BLUE:System.out.println("蓝色");break; }