首页 > 代码库 > java学习笔记 2
java学习笔记 2
关于raw type
刚好在预习龙书,就把官网上提供的那份java写的前端代码拖了下来看看。
导入eclipse,发现有一堆warning,其中一个是Reference to generic type Hashtable<K, V> should be parameterized。
google之,发现了一篇不错的讲解:What is a raw type and why shouldn‘t we use it?
简而言之,就是泛型和C++的模版一样,要写上类型,不然要是玩坏了,编译的时候不给你报错,等着runtime来挂就不好了。嗯这代码很老了吧……再仔细一看,貌似没什么注释也,还是默默看书好了……
在eclipse导入已有的project
按照core java上的指示,去导入一个project看看……咦,新版的界面没有create project from existing source了……
google一下找到了解决方案: Eclipse Community Forums: Newcomers » helios & "create project from existing source"
在创建新project的时候去掉Use default location的勾,选择对应文件夹就行了。
serialVersionUID
导入另一个project看看,这回有一个warning:The serializable class ImageViewerFrame does not declare a static final serialVersionUID field
再google之,解答:What does it mean: The serializable class does not declare a static final serialVersionUID field?
OK,那什么是serializable class?学其他语言的时候貌似看到过,但是没仔细看什么意思。
解答在这里:
- Serialization - Wikipedia, the free encyclopedia
- Serializable (Java Platform SE 7 )
原来就是和python的pickle、JS的JSON类似作用的东西~ 用来把对象转化成可存储的格式叫serialization,把类从存储的byte里读出来叫deserialization。eclipse给出这个警告,是因为加一个UID能够确保serialization和deserialization用的是同一版本的类,以免中途这个类修改过,就会牛头不对马嘴了。
要解决这个warning,可以在类中随便加一个UID,比如eclipse给出的第一个解决方案就是加上:
private static final long serialVersionUID = 1L;
不过这个东西没有也不碍事,就是没那么安全而已,所以才只是个warning。
demo: ImageViewer
仔细看了一下这个demo的代码
- main函数里看到了多态(JFrame frame = new ImageViewerFrame();然后调用虚函数)
Java里貌似可以匿名地implement一个interface,然后直接传给一个函数,像这样:
obj.method(new Interface(){ // override some methods...});
- 这个代码写了一个继承JFrame的ImageViewerFrame类,在它的构造函数里用Swing的各种轮子来画界面
demo: WelcomeApplet
传说中的Java applet!好怀旧的感觉……
- 这个代码写了一个继承JApplet的类,并且加了一个方便跳转URL的小函数makeAction
- 也是用了Swing的各种轮子来画了个界面
- 这回编译出.class之后,用JDK附带的appletviwer来打开这份代码附带的一个html,里面有一个<applet>标签,其中指明了要用这个编译出的名字的.class。如果使用这种方式打开,<applet>标签以外的东西都不会被显示。
- 除了用命令行,也可以用eclipse的run as java applet来跑
- 此外还可以在编译完class之后,直接用浏览器打开那个html来跑,这回就可以看到<applet>以外的东西了(但是我家firefox和chrome都以安全原因把这玩意儿给block了……2333)
Not a Hello World
- Java 的类也要自带access modifier(public, private..., etc)
- Java里无论任何函数都必须作为方法依存于类,所以main函数起码要有个空壳class
- 代码文件的basename要和代码里那个public类的名字一样
编译出的.class里面是bytecode,可以反编译回去,跑的时候用
java className
就行了,记得不要加.class
- main函数总应该是static的。从Java 1.4开始,main函数一定要是public的
- Java的main函数不用return 0,正常结束的exit code就是0,如果要用其他exit code结束,可以调用System.exit(code)
- 我自己试了一下把main函数写到另外一个文件的另一个类里,在里面调用另一个类,这样也是OK的,看了一下eclipse怎么给我跑的,原来是用了classpath,只要指明用的类编译出来的.class在哪里就OK了
- 如果函数不需要参数,只要用()就好了,里面不用加void
- 打印东西到终端主要用到System.out(这是个对象)的几个方法
- println会自动末尾带换行(print line)
- print不会带换行
- printf可以用C风格的format string
Java的注释
- 如果你用了/** ... */ (多个星号)的话,可以用来自动生成文档(和python的docstring差不多的东西?)
- 和C/C++一样,Java的/**/也是不能嵌套滴
数据类型
- Java的各种整型和char都是跨平台的一致
- 和C/C++一样,前缀换数制,后缀换类型
- Java 7还支持一个很nice的东西:像英文写数字的,一样,可以用_分割长的数字,比如1000000=1_000_000,编译器编译的时候会自动无视它们,但是人眼看着会舒服一点(不用数位数了呵呵呵)
- Java的primitive type里没!有!unsigned type!(反正留着也是麻烦2333)
- Java有NaN,要用就写Double.NaN,用法和JS的类似,整数除0抛异常,浮点数除0得到NaN
Java里的整数和布尔类型是没有隐式转换的,也就是说你不能if(0)这样玩,所以就可以防止
if (x = 0)
这种手误,编译的时候就给你报错抓出来(果然是提防猪队友指定语言……)
变量
- Java的变量名可以用$,但是基本上是预留给自动生成的代码用的,自己写就别用了
- Java里是没有C/C++中的那种declaration和definition之分的,你不能像C一样一处写个extern int i,一处写个int i = 10,或者C++那样头文件写个class declaration,.cpp写个definition。在Java里,大家都写一块儿(.java文件里)。关于这点可以参考:What is the difference between declaration and definition in Java?。当然如果是JS里的那种declaration(int i)和definition(i = 10)之分,那还是有的。
Java里的常量用final,比如类的静态常量就可以用
static final int x = 10;
这样声明。诡异的是const也是Java的保留字,虽然现在的Java语法里根!本!没用它!
运算符
因为浮点数运算的一致性实在太难保证了(有些处理器用80bit来保存浮点数,简直不能做朋友),所以Java默认是不保证这个的,除非你在函数名上加个strictfp,里面的运算就会保证这个,比如
public static strictfp void func() {...}
- Java的&&和||也是短路的,&和|就不是了
- 对int左右移的时候,右算子会%32,long的话%64
- >>是算术右移(用sign bit填充),>>>是逻辑右移(用0填充),C/C++这方面是implementation dependent的,所以这算是Java的一个改进
和JS一样,常见的数学运算都是Math这个类的静态方法。如果不想每次都写Math.xxx这样好麻烦,可以用
import static java.lang.Math.*
(可以看出java的import是有static之分的,和python不同的是想不加类名直接import,没有from xxx import xxx这种东西)
cast的方法和C一样,注意布尔型是不给cast的,手动都不行!如果你要cast,就只能类似这样
i == 0 ? true : falseb ? 1 : 0
- Java没有逗号运算符,不过在for的第一和第三个空隙里可以用逗号分开表达式
enum
- Java里也有这个东西,囧
字符串
- Java自带一个String类,掌声鼓励~
- 用法貌似和JS差不多,Java里的对象和JS一样都是引用
- Java的String也是immutable的,要改呢你就用各种方法和运算符算好了之后赋值给自己就行了
- 注意判断字符串内容相等要用s.equals(t)这样的形式,或者可以用s.compareTo(t) == 0(貌似在algorithms里见到过这个注意,compareTo是因为它implement了一个叫Comparable的interface)。如果用了==,判断的是引用位置是否相等而已。(和JS里用new String("xxx")得到的对象的用法类似)。
- 关于各种比较方法的资料
- Java: ==, .equals(), compareTo(), and compare()
- Java Strings: compareTo() vs. equals()
- 总的来说推荐用equals(),简单直观,少抛奇怪的异常
- 还有一个很方便的equalsIgnoreCase()可以用
- 空字符串和null的区别类似于JS
- 要得到单个字符,用charAt,从0数起
- 因为Java的String都是用unicode的,所以会有char和code point的区别
- String的很多方法都和JS蛮像的……JS的大腿抱得真是好
- 如果要将一堆小的字符串汇集成一个大的字符串,可以用StringBuilder(Java 5引入的新类,以前用的是StringBuffer)