首页 > 代码库 > 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)