Java学习笔记

从C++到Java

Java是C系编程语言,许多语法与C、C++相似,对于C/C++开发者来说,入门相当容易,但也更容易忽略其间某些细微的差别,需要特别注意:

1. Java成员函数必须在类的内部定义

实际上,C++也允许在类的内部给出成员函数的定义,只是由于C++沿用了C语言的include机制,而这种定义方式会导致函数重定义,因此大部分情况下会将成员函数的定义与类的定义分离。但Java采用的是import机制避免了上述问题,这无疑是一大进步。

2. Java函数参数不允许有缺省值

3. Java没有操作符重载

除了String类的'+'和'+='之外,JAVA摒弃了几乎所有的操作符重载。因此,在使用不包括基本类型在内的Java对象时,不要使用操作符,要使用对应的方法。比如,判断两个String类是否相同要使用equals,而不是'=='。

4. Java没有virtual关键字

Java使用的是彻底的动态绑定机制,所有的成员函数都是可重载的,因此也就不需要virtual的关键字。

5. Java没有delete关键字

声明一个Java变量之后需要使用new创建一个对象实例对其初始化,否则该变量为null,然而,由于Java拥有自动垃圾回收机制,对象不需要显式删除,因此也就不需要delete关键字。

6. Java不支持多继承

7. Java的基本类型不支持无符号数

8. Java的内部嵌套类更复杂

Java允许内部嵌套类访问顶层类的成员和方法,即使这些成员和方法是私有的。Java允许内部嵌套类匿名,匿名的内部嵌套类可以出现在任意的代码段中,对应的对象在声明该类的同时被创建,匿名的嵌套类不仅可以访问顶层类的成员和方法,还可以访问局部变量。

public class Test {
    protected final String name = "Hello";
    protected void Run() {
        new Runnable() {
            public void run() {
                System.out.println(name);  /* access members of outer class */
                System.out.println(Test.this.name); /* access the instance of outer class directly */
            }
        }.run();
    }
    public static void main(String[] args) {
        Test t = new Test();
        t.Run();
    }
}

在以上代码中,Test类的Run()方法会创建一个实现了Runnable接口的匿名类,并调用该匿名类的run方法。

需要注意的是,内部嵌套类必须由其上层类的对象来创建。也就是说,内部嵌套类的对象不能脱离其上层类独立存在:

class A {
    class B {
       void foo() {}
    }
    void foo() {}
}
 
public class Test {
    public static void main(String[] args) {
        A.B b = new A.B(); 
    }
}

以上代码编译是无法通过的,因为不可能在没有创建A的对象的前提下创建A.B的对象,正确的方法是:

class A {
    class B {
       void foo() {}
    }
    void foo() {}
}
 
public class Test {
    public static void main(String[] args) {
        A a = new A();
        A.B b = a.new B();
    }
}

9. Java不支持临时变量

Java不再支持所谓临时对象(即存放在栈中的对象),所有的对象都必须在堆上创建,此外,Java通过垃圾回收机制自动销毁不再使用的对象。对于开发者来说,不再需要在开发之前确定所使用的对象的确切数目和生存周期,这一定程度上简化了复杂业务模型的程序结构,当然,代价是牺牲了一部分性能——毕竟,在栈上分配和销毁对象要快得多。1)

Java的运行环境

运行Java需要安装JRE,其中包含了Java虚拟机和一系列的系统库。PC操作系统对Java的支持都很好,Mac OS X内置了JRE,各种Linux桌面发布版都有GNU的JRE实现,Windows系统也可以安装Oracle发布的JRE软件包。一些移动设备提供对J2ME的支持,但Android的情况有些特殊,它使用了Java语言,但没有使用Oracle的虚拟机和系统库,也并不兼容于Oracle发布的任意一个Java规范,甚至连Java字节码都不是标准的,因此它面对着Oracle的法律诉讼,然而没有人知道最终的结局。

上面也提到了,Oracle公司为Java平台制定了若干规范,主要包括Java ME, Java SE以及Java EE,Java技术是公开的,但Oracle对Java的使用提出了许多限制,比如必须满足其定义的某个规范等。

除此之外,Java还可以以Applet的形式在浏览器中运行,也可以以Servlet的形式在http服务器上运行,从这个角度看,Java还是JavaScript和PHP的竞争者。

(以上提到的Oracle所做的关于Java的事情其实大多是SUN完成的,可是Oracle购买了SUN)

Java的开发环境

使用Java语言进行软件开发需要JDK,其中包含了Java的编译器,一些必要的系统工具以及一个JRE。SUN与2007年以GPL方式开发了JDK的源码并将其贡献给OpenJDK。

Eclipse则是目前最通用的一个Java IDE,可以从Oracle的网站下载。

JNI

JNI提供一种机制允许java语言调用C语言的函数。

首先在Java中,这样的函数要使用native关键字,而且无需定义。在某个外部的C语言库中,要定义对应的函数实现。和Java中对应的函数略有不同,首先名字增加了一系列前缀,其次多出两个参数:第一个是JNIEnv *env,第二个是jobject thiz,第一个是JNI环境对象的指针,用于完成JNI相关方法的调用;第二个是对应java对象的引用。其他的参数和Java中声明的native函数保持一致,类型上稍有变化。对于基本Java类型,如char, int, float等,在JNI中对应jchar, jint, jfloat,可以直接使用;对于Java的对象,在JNI中映射为jobject;而对于String和数组,在JNI中映射为jstring和 jarray,需要通过特定的JNI方法来使用。

这样处理jobject类型的参数: - 首先通过thiz可以得到一个jclass cls = env→GetObjectClass(thiz),表示对应Java对象所属的类; - 然后通过jfieldID fid = env→getFiledID(cls, ”…name”, ”…signature”)可以获取该Java对象的成员ID; - 最后通过env→GetIntField等方法即可获取某个成员ID对应的值。 - 此外,如果没有thiz,也可以通过env→FindClass来获取jclass,然后通过env→NewObject来创建对应的 Java对象,并先后通过env→getFiledID和env→SetIntField等方法来设置新对象的成员的值。

1) Thinking in Java (4th Edition), Bruce Eckel
 
tech/programming/java.txt · Last modified: 2014/11/10 08:22 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki