Java程序设计简介



这篇教程介绍了Java编程语言的安装和使用,并且包含一些编程实例。

历史

Java 编程语言由Sun微电子公司的James Gosling于1991年创建。1995年发布第一个版本(Java 1.0)。2010年 Sun 微电子公司被 Oracle 公司收购,现在 Java 语言由 Oracle公司控制和管理。2006年Sun宣布Java遵循GNU General Public License (GPL), Oracle继续该项目,即OpenJDK。随着时间的推移,新的增强版本的 Java 已经发布,最新的版本是 Java 1.8 即 Java 8。

Java由规范确定,包含编程语言、编译器、核心库和JVM (运行时Java virtual machine)。Java运行时允许软件开发者用其他语言编码,仍然运行在Java虚拟机上。 Java平台通常与Java虚拟机和Java核心库相关联。

Java 虚拟机

Java 虚拟机(JVM)可以理解为是由软件实现的虚拟计算机,可以像物理计算机一样执行程序代码。Java 虚拟机在不同操作系统下有特定的版本,比如:针对 Linux 操作系统的版本与针对 Windows 操作系统的版本是不一样的。

Java程序由 Java 编译器编译成字节码(bytecode),编译后的字节码由 Java 虚拟机解释执行。


Java程序设计简介_第1张图片

 JRE 和 JDK

Java 的发布版本有两种,Java Runtime Environment(JRE)以及 Java Development Kit(JDK)。


Java Runtime Environment(JRE)包含运行 Java 程序需要的必要组件:Java 虚拟机以及 Java 类库。

Java Development Kit(JDK)包含用来创建 Java 应用程序的必要工具,比如,Java 编译器、Java 虚拟机以及 Java 类库。

Java 语言的特点

Java 语言的设计目标是:一次编写到处运行。

Java 语言有以下特点:

  • 平 台无关性:Java 使用 Java 虚拟机运行 Java 程序,Java 虚拟机相当于应用程序和操作系统间的抽象层,应用程序不会直接访问操作系统。这使得 Java 应用程序具备高度的可移植性。一个兼容标准和遵循规则的 Java 应用程序可以无需修改的在所有已支持的平台上工作,例如: Windows 和 Linux。

  • 面向对象的编程语言:除了原生数据类型,Java 语言中一切皆对象。

  • 强类型编程语言:Java 语言是强类型编程语言。比如:变量类型需要预先定义,严格的类型转换检查(大多数情况下有程序猿完成)。

  • 解 释性和编译型语言: Java 源代码被编译成字节码(bytecode)这样使得 Java 语言具备平台独立性。这些字节码(bytecode)指令由 Java虚拟机(JVM)解释执行。JVM 使用 Hotspot 编译技术会将性能相关的字节码指令转换为对用操作系统的二进制代码执行。

  • 自动内存管理: Java 。管理新创建对象的内存分配和回收工作应用程序代码不直接访问内存。由称之为垃圾回收(garbage collector)的机制自动删除没有无引用的对象。

Java 语言的语法与 C++ 语言的语法非常接近,Java 语言是大小写敏感的,比如: myValue 变量与 myvalue 变量是两个不同的变量。

Java语言的开发过程


Java 源代码文件是一个纯文本文档,Java 程序员通常在 Integrated Development Evvironment(IDE)中编写 Java 程序。IDE是帮助程序员完成编码工作的工具,它具备自动格式化代码、语法高亮等功能。

Java 程序员(或 IDE)调用 Java 编译工具(javac)编译源代码,Java 编译工具会将源代码编译成字节码(bytecode)指令。这些指令保存在 .class 文件中由 Java 虚拟机(JVM)来运行。


垃圾回收(Garbage collector)


JVM 自动回收没有被引用的内存空间,它会检查所有对象的引用并查找那些对象可以被自动回收。垃圾回收机制使程序员无需手工管理内存,但是程序员还是需要保证程 序中没有不需要的对象引用,否则垃圾回收机制就无法自动释放对象内存。我们通常把不需要的对象引用通常被称为“内存泄漏”。

Classpath


Java 编译器以及 Java 运行时通过类路径(classpath)来查找和装载 .class文件。比如,如果你打算在应用程序中使用第三方 Java 类库那么你需要把类库的路径添加到你的类路径中,否则你的应用程序无法编译或者运行。

安装 Java

 

检查安装

你的计算机可能已经安装了 Java,你可以在控制台中使用下面命令来测试 Java 是否已安装(如果你使用 Windows 操作系统,可以按下 Win+R,输入 cmd 后回车即可打开控制台):

java -version

如果你的计算机已经安装了 Java,你应该会看到输出已安装的 Java 版本信息。如果命令行返回应用程序没有找到,那么你就需要安装 Java 了。

安装 Java

在 Ubuntu 操作系统中,你可以使用下面的命令安装 Java:

sudo apt-get install openjdk-7-jdk

java8的安装:

    

# install Java from the OpenJDK project
sudo apt-get install openjdk-8-jdk
# in case you prefer the Oracle Java distribution 
# you can alternatively use the following commands
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer

    对于 Microsoft Windows 操作系统,可以到 Oracle 官网下载对应的安装包,官网也有相应的文档来指导你如何在其他操作系统上安装 Java。

如果在安装过程中出现了问题,可以使用“how to install JDK on your_os"关键词在谷歌搜索,记住把 "your_os" 替换为你的操作系统名称哦,比如:Windows、Ubuntu、Mac OS X 等等。

验证安装

回到刚才的命令行执行下面的命令:

java -version

你会得到下面的输出内容:

$ java -version
java version "1.7.0_79"
OpenJDK Runtime Environment (IcedTea 2.5.6) (7u79-2.5.6-0ubuntu1.14.04.1)
OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)

 如何查看当前使用的是32位或64位版本的 Java

在64位操作系统上你可以使用32位或64位版本的Java,如果 java -version 命令的输出中包含 64-bit 这样的字符串说明你正在使用的 Java 版本是64位的,否则你正在使用的 Java 版本是32位的。下面的是64位版本的输出:

java version "1.7.0_25"OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.13.04.2)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

编写源代码

下面的 Java 代码是在 Linux 操作系统命令行上使用文本编辑器(vim、emacs等)编写的。其他操作系统上也类似,这里就不再做介绍了。

首先需要新建一个目录来保存源代码,这里我们使用目录 \home\vogella\javastarter。如果你使用 Windows 目录可能是 c:\temp\javastarter,后面我们会使用 "javadir" 来代表这个路径。

打开一个文本编辑器,不如:Linux操作系统下的 gedit、vim、emacs等,Windows下的 Notepad等,然后输入以下代码:

HelloWorld.java:

// a small Java program 
public class HelloWorld {  public static void main(String[] args) {
    System.out.println("Hello World");
  }
}

注意:不要使用富文本编辑器,如:Microsoft Word 或者 LibreOffice 来编写源代码。

 

将源代码保存到 “javadir” 目录下的 HelloWorld.java 文件中。Java 源文件名称始终要与源代码中得类名一致,并且以 .java作为后缀。这个例子中源文件名为 HelloWorld.java 因为我们定义的类名是 HelloWorld

编译、运行

打开一个Shell(Linux以及Unix-like)或者命令行(Windows),使用 cd javadir 进入 "javadir" 目录,在我们的例子中命令是 cd \home\vogella\javastarter。使用 ls (Window中是 dir)来验证源文件是否存在。

使用下面命令编译源文件:

javac HelloWorld.java

命令完成后,重新使用 ls(或者 dir)命令查看目录内容,可以看到目录中多出一个 HelloWorld.class 文件,说明你已经成功的将源代码编译成字节码了。


提示:默认情况下编译器会将每个类文件放在和源文件下共同的目录中。你可以在编译时使用 -d 参数来指定不同的目录。

现在可以运行你的第一个 Java 应用程序了。确保你还在 "javadir" 目录,然后执行下面命令来运行程序:

java HelloWorld

程序会在终端输出 "Hello World" 字符串,参考下图

Java程序设计简介_第2张图片

使用类路径(classpath)

你可以通过指定类路径从其他位置运行应用程序。还是打开Shell或者控制台,然后随便进入一个目录,输入以下命令:

java HelloWorld

如果你当前不在编译后类文件所在的目录,那么 Java 虚拟机会提示错误:"Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld"。

要正确运行程序,输入下面的命令(将mydirectory替换为你的”javadir"):

java -classpath "mydirectory" HelloWorld

这样你又可以看到 "HelloWorld" 字符串输出了。

Java 语言结构

基础:包(Package)、类(Class)和对象(Object)

了解 Java 的包(Package)、类(Class)和对象(Object)这些基础术语是非常重要的,这部分内容将概要的介绍这些术语。

包(Package)

Java 使用包来组织类,通常按照业务逻辑将类分组到不同的包中。比如:应用程序的所有图形界面可能被分组到 com.vogella.webapplication.views 包中。

通常的做法是使用公司域名的倒序作为顶层包,比如:公司的域名是 "4byte.cn" 那么这个公司 Java 应用的顶层包名可能是 cn.4byte

包的另一个重要用途是避免类命名冲突,类命名冲突是指两个开发人员为他们编写的类使用了同样的全限定名。Java 中类的全限定名是 报名+‘.'+类名,比如:cn.4byte.HelloWorld

如果没有包,当两个程序猿同时给他编写的类起名为Test 时就会产生命名冲突(而且操作系统也无法创建文件)。结合 Java 包机制,我们可以明确的告诉虚拟机我们将使用哪个 Test 类,比如:第一个程序员将 Test 类放到 report 包中,另一个程序员将他写得 Test 类放到 xmlreader 包中,那么他们就可以通过全限定名来明确区分两个类 report.Test 以及 xmlreader.Test。

类(class)

定义:类是一个模板,用来定义对象的数据以及行为,可以理解类为对象的蓝图。

在 Java 中使用 class 关键字来定义类,类名的第一个字母必须大写。类体需要在'{..}'中定义。如:

MyClass.java:

package test;

class MyClass {

}

类的数据保存在属性中,类行为由方法实现。Java 源文件需要以 "类名“ + ".java" 的形式保存。

对象(Object)

定义:对象是类的一个实例。 对象是真实的元素具有数据和可执行的操作。每一个对象都是依据类的定义进行创建的。

继承

一个类可以从另一个类派生,我们称之为子类。另一个常用的说法是:一个类扩展另一个类。被派生(或继承或被扩展)的类我们称之为"父类"。

继承允许子类继承父类的方法和行为(这里还没有提到访问限定问题,会在后面介绍),下面的代码演示了如何继承一个类,Java 是单继承体系(与C++不同)一个类只能有一个父类。

MyBaseClass.java:

class MyBaseClass {

  public void hello() {
    System.out.println("Hello from MyBaseClass");
  }
}
public class MyExtensionClass {
}

Object是所有类的父类

Java 中所有的类都隐式继承 Object 类。Object 类为每一个 Java 对象定义了下面的一些方法:

  • equals(other) 检查当前对象是否等于other对象

  • getClass() 返回对象的类(Class对象)

  • hashCode() 返回对象的唯一标示符

  • toString() 返回当前对象的字符串描述


Modem.java

public class Modem {
    int speed;

    public void displaySpeed() {
        System.out.println("Speed: " + speed);
    }
}

CableModem.java

public class CableModem extends Modem {
    String method = "cable connection";

    public void connect() {
        System.out.println("Connecting to the Internet ...");
        System.out.println("Using a " + method);
    }
}

DslModem.java

public class DslModem extends Modem {
    String method = "DSL phone connection";

    public void connect() {
        System.out.println("Connecting to the Internet ...");
        System.out.println("Using a " + method);
    }
}


ModemTester.java

public class ModemTester {
    public static void main(String[] args) {
        CableModem surfBoard = new CableModem();
        DslModem gateway = new DslModem();
        surfBoard.speed = 500000;
        gateway.speed = 400000;
        System.out.println("Trying the cable modem:");
        surfBoard.displaySpeed();
        surfBoard.connect();
        System.out.println("Trying the DSL modem:");
        gateway.displaySpeed();
        gateway.connect();
    }
}

Point3D.java

import java.awt.*;

public class Point3D extends Point {
    public int z;

    public Point3D(int x, int y, int z) {
        super(x,y);
        this.z = z;
    }

    public void move(int x, int y, int z) {
        this.z = z;
        super.move(x, y);
    }

    public void translate(int x, int y, int z) {
        this.z += z;
        super.translate(x, y);
    }
}

PointTester.java

import java.awt.*;

class PointTester {
    public static void main(String[] args) {
        Point object1 = new Point(11,22);
        Point3D object2 = new Point3D(7,6,64);

        System.out.println("The 2D point is located at (" + object1.x
            + ", " + object1.y + ")");
        System.out.println("\tIt's being moved to (4, 13)");
        object1.move(4,13);
        System.out.println("The 2D point is now at (" + object1.x
            + ", " + object1.y + ")");
        System.out.println("\tIt's being moved -10 units on both the x "
            + "and y axes");
        object1.translate(-10,-10);
        System.out.println("The 2D point ends up at (" + object1.x
            + ", " + object1.y + ")\n");

        System.out.println("The 3D point is located at (" + object2.x
            + ", " + object2.y + ", " + object2.z + ")");
        System.out.println("\tIt's being moved to (10, 22, 71)");
        object2.move(10,22,71);
        System.out.println("The 3D point is now at (" + object2.x
            + ", " + object2.y + ", " + object2.z + ")");
        System.out.println("\tIt's being moved -20 units on the x, y "
            + "and z axes");
        object2.translate(-20,-20,-20);
        System.out.println("The 3D point ends up at (" + object2.x
            + ", " + object2.y + ", " + object2.z + ")");
    }
}

异常处理

异常是表示应用程序的运行时的    错误事件。它破坏了应用程序的正常流程。通常异常会逐层抛出直到被捕获为止。


Java程序设计简介_第3张图片   

 检查异常示例:

public void fileNotFoundExceptionIsCaughtInside() {
  try {
    createFileReader();
  } catch (FileNotFoundException e) {
    logger.error(e.getMessage(), e);
  }
}    
    
public void fileNotFoundExceptionIsReThrown() throws FileNotFoundException {
  createFileReader();
}

public void createFileReader() throws FileNotFoundException {
  File file = new File("/home/Documents/JavaTraining.txt");
  // creating a new FileReader can cause a FileNotFoundException
  new FileReader(file);
}

运行时异常是方法没有提及的异常,不必显式地捕获。最有名的运行时异常是NullPointerException异常,其运行过程中发生,当一个对象调用为空时。     

public void causeANullPointerException() {
  String thisStringIsNull = getMessage(false);
  
  // because the thisStringIsNull object is null
  // this will cause a NullPointerException
  thisStringIsNull.toLowerCase();
}

public String getMessage(boolean messageIsAvailable) {
  if(messageIsAvailable) {
    return message;
  }
  
  return null;
}

  

又一实例:

public class NewCalculator {
    public static void main(String[] arguments) {
        float sum = 0;
        for (int i = 0; i < arguments.length; i++) {
            try {
                sum = sum + Float.parseFloat(arguments[i]);
            } catch (NumberFormatException e) {
                System.out.println(arguments[i] + " is not a number.");
            }
        }
       System.out.println("Those numbers add up to " + sum);
    }
}

捕捉多个异常:

public class NumberDivider {
    public static void main(String[] arguments) {
        if (arguments.length == 2) {
            int result = 0;
            try {
                result = Integer.parseInt(arguments[0]) /
                    Integer.parseInt(arguments[1]);
                System.out.println(arguments[0] + " divided by " +
                    arguments[1] + " equals " + result);
            } catch (NumberFormatException e) {
                System.out.println("Both arguments must be numbers.");
            } catch (ArithmeticException e) {
                System.out.println("You cannot divide by zero.");
            }
        }
    }
}

  Exception是所有异常类的子类。 |可用于分割类。

try {
// statements that might cause the exception
} catch (Exception e) {
// what to do when the exception occurs
} finally {
// statements to execute no matter what
}

finally部分不管是否有异常都会执行。

抛出异常:

try {
    principal = Float.parseFloat(loanText) * 1.1F;
} catch (final Exception e) {
    System.out.println(“Error “ + e.getMessage());
    throw e;
}

忽略异常:

public loadURL(String address) throws MalformedURLException {
    URL page = new URL(address);
    loadWebPage(page);
}

实例:

import java.net.*;
public class HomePage {
    String owner;
    URL address;
    String category = "none";
    public HomePage(String inOwner, String inAddress)
        throws MalformedURLException {
        owner = inOwner;
        address = new URL(inAddress);
    }
    public HomePage(String inOwner, String inAddress, String inCategory)
        throws MalformedURLException {
        this(inOwner, inAddress);
        category = inCategory;
    }
}
import java.net.*;
public class PageCatalog {
    public static void main(String[] arguments) {
        HomePage[] catalog = new HomePage[5];
        try {
            catalog[0] = new HomePage("Mark Evanier",
                "http://www.newsfromme.com", "comic books");
            catalog[1] = new HomePage("Todd Smith",
                "http://www.sharkbitten.com", "music");
            catalog[2] = new HomePage("Rogers Cadenhead",
                "http://workbench.cadenhead.org", "programming");
            catalog[3] = new HomePage("Juan Cole",
                "http://www.juancole.com", "politics");
            catalog[4] = new HomePage("Rafe Colburn",
                "http://www.rc3.org");
            for (int i = 0; i < catalog.length; i++) {
                System.out.println(catalog[i].owner + ": " +
                    catalog[i].address + " -- " +
                    catalog[i].category);
            }
        } catch (MalformedURLException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}

Java 接口(interface)

接口(interface)

接口是一个契约,用来描述一个实现类可以完成什么任务,接口并没有去实现契约,契约是由实现接口类来实现的。

接口的定义方法跟类很相似,接口中可以定义方法,接口中只能定义抽象方法,不能定义任何具体方法。接口中定义的方法默认都是:public abstract 方法。

接口中可以定义常量,常量默认是:public static final。

实现接口的类需要实现接口中定义的全部方法(如果不想实现部分方法,那么需要定义这个类为抽象类)。如果重写(override)接口中得方法,可以在方法上使用 @override 注解。

下面是定义接口以及实现接口的代码示例:

public interface MyInterface {

    // constant definition
    String URL = "http://www.vogella.com";

    // public abstract methods
    void test();
    void write(String s);
    
    // default method
    default String reserveString(String s){
      return new StringBuilder(s).reverse().toString();
    }
}
public class MyClassImpl implements MyInterface {
    @Override
    public void test() {
    }
    @Override
    public void write(String s) {
    }
  
    public static void main(String[] args) {
        MyClassImpl impl = new MyClassImpl();
        System.out.println(impl.reserveString("Lars Vogel"));
    }
}

没有main方法的,有applets(在web页面中执行)和servlets(在web服务器中执行)。

接口演变

Java 8以前不能给接口创建新方法。Java的8引入了默认方法,类可以重载默认方法    。


多重继承

如果类实现两个接口且这些接口提供相同的默认方法,Java解释规则如下:

  • 父类大于父接口 - 如果类继承父类    和父接口的方法,类继承父类方法。

  • 子类型大于父类型。

  • 在其他情况下的类需要实现的默认方法。见下面列子:

public interface A {
  default void m() {}
}

public interface B {
  default void m() {}
}
    
public class C implements A, B {
  @Override
  public void m() {}
}

        实现时可以调用父类方法:

public class C implements A, B {
  @Override
  public void m() {A.super.m();}
}

函数接口(Functional interfaces)

所有只有一个方法的接口称之为函数式接口(Functional interfaces)。函数式接口的优势是可以结合lambda表达式(“闭包”或“匿名方法”)一起使用(函数式编程 )

                Java 编译器可以自动识别函数式接口,然而最好在函数式接口上使用 @FunctionalInterface 注解来体现你的设计意图。

一些 Java 标准库中的函数式接口: 

  • java.lang.Runnable 

  • java.util.concurrent.Callable

  •  java.io.FileFilter 

  • java.util.Comparator*

  •  java.beans.PropertyChangeListener

JDK 的 java.util.function 包包含了一些常用的函数式接口: 

 

Predicate<T>:对象的布尔值属性

Consumer<T>:对象的action

Function<T , R>:转换T为R的函数

Supplier<T>:提供T的实例,类似工厂函数。

UnaryOperator<T>:转换T为T的函数

BinaryOperator<T>:转换(T, T)为T的函数

   

注解                

注解有运行时(RetentionPolicy.RUNTIME)和开发时(RetentionPolicy.SOURCE)两种。       

重写方法和@Override 注解

如果一个类继承另一个类,它会继承父类的方法。如果它想要改变父类的一些方法,可重写这些方法。可以在子类中用相同的方法签名重写父类方法。

你可以使用 @Override 注解明确告诉后续的维护代码的程序员以及 Java 编译器,重写了父类对应方法。

@Deprecated表示不推荐使用。                

Java 8提供了类型注解,比如:

    

@NonNull String name;
List<@NonNull String> names;
class UnmodifiableList<T> implements @Readonly List<@Readonly T> {...}
email = (@Email String) input;
new @Information MyObject();
void doSomething() throws @ImportantForMe MyException { ... }


下面的代码演示了如何重写父类的方法:            

MyBaseClass.java:

class MyBaseClass {

  public void hello() {
    System.out.println("Hello from MyBaseClass");
  }
}

MyExtensionClass2.java:

class MyExtensionClass2 extends MyBaseClass {
  
  @Override                
  public void hello() {
    System.out.println("Hello from MyExtensionClass2");
  }
}

最好始终在重写父类方法时使用 @Override 注解,这样编译机可以帮助开发人员检查是否正确的重写了父类中对应的方法。

变量和方法

原始数据类型和应用

Java 中主要有两大类类型,原始类型(比如:boolean、short、int、double、float、char 以及 byte)和引用类型(比如:Object 和 String)。

       

原始数据类型

原始数据类型变量用来描述:数字、布尔值(true/false) 或者字符。原始类型变量不是    对象,因此不能通过这些变量执行方法调用。

*,-,+,/只能在原始类型上使用,不过 + 可以在字符串上使用,代表字符串拼接。


int  –2.14 billion to 2.14 billion
float    decimal numbers of up to 38 figures
double     decimal numbers up to 300 figures
character 单个字符
string
byte    –128 to 127
short     –32,768 to 32,767
long    –9.22 quintillion to 9.22 quintillion


long salary = 264_400_000; java 7 支持。
变量名: 字母、下划线或者美元符号开头。



指明数值类型:
float pi = 3.14F;
没有F默认是double,L对应long integer, D对应float。


引用类型

引用类型变量代表到一个对象的引用(或者指针)。如果你修改引用类型变量的值,那么这个变量会指向性的对象或者 nullnull代表空引用或者引用到一个不存在的对象。修改应用对象变量并不会修改它指向的对象。修改指向对象的内容也不会影响指向它的引用。

类型自动装箱(Autobox)和拆箱(Wrapper)

每一个原始类型都有对应的引用类型(或者说对应的类)。这些引用类型可以在一个对象中保存对应的原始类型。比如:java.lang.Integer 和 int。

将原始类型转换到一个引用类型的实例或者相反的过程称之为:装箱和拆箱。Java 会在必要的情况下自动执行这些过程。这允许你在调用参数为对象的方法时传递原始类型,这个过程称之为自动装箱。        

变量

Java 程序在运行过程中使用变量来保存过程值。变量可以是原始类型也可以使引用类型。原始类型变量保存对应的值,而引用类型变量保存的是对象的引用(指针)。因此,如果你比较两个引用类型变量,你实际上是在比较两个引用类型变量是否指向同一个对象。因此,比较对象时需要使用 object1.equals(object2) 。

实例变量

实例变量定义在对象一级,在对象生命周期内都可以访问。实例变量可以赋予任何访问控制并且可以被标注为 final 或者 transient

被标注为 final 的实例变量在被赋值后是不能被改变的(实际就是只能被赋值一次)。通常情况下,final变量有3个地方可以赋值:直接赋值,构造函数中,或是初始化块中。

由于在java的语法中,声明和初始化是联系在一起的,也就是说:如果你不显示的初始化一个变量,系统会自动用一个默认值来对其进行初始化(如 int就是0)。对于final变量,在声明时,如果你没有赋值,系统默认这是一个空白域,在构造函数进行初始化,如果同时也是是静态的 (static),则可以在初始化块赋值。

局部变量(Local variable)

局部变量不能赋予除 final 以外的访问控制修饰,final 修饰的局部变量在赋值后不可以被改变。

局部变量不会分配默认值,因此需要在使用前初始化它们。        

方法

方法是具备参数表以及返回值的代码块,需要通过对象来调用方法,下面是一个 tester 方法的定义:

MyMethodExample.java:

public class MyMethodExample {
  void tester(String s) {
    System.out.println("Hello World");
  }
}

方法可以定义可变参数(var-args),定义类可变参数的方法可以接受0个或者多个值(语法:type ... name;,一个方法只能定义一个可变参数,而且必须是方法参数表的最后一个参数定义。

重写父类方法:子类方法需要与父类方法有完全相同个数和类型的参数以及相同类型的返回值。

重载方法:重载方法是指多个方法有相同的方法名,但是有不同个数或类型参数,返回类型不同不能区分重载方法。

主方法(Main method)

具有 public static 签名的方法可以用来启动 Java 应用程序(主入口),这个方法通常是 main 方法

public static void main(String[] args) {

}

构造函数(Constructor)

类包含它的构造函数,构造函数式在类构造时被调用的方法(执行 new SomeClass 时调用)。构造函数的声明方式与方法类似,唯一的要求就是构造函数名必须与类名相同且不许定义返回类型。

类可以有多个重载的构造函数,参考上一节对重载的描述。每一个类需要有至少一个构造函数。下面构造函数代码示例:

MyConstructorExample2.java:    

public class MyConstructorExample2 {

  String s;

  public MyConstructorExample2(String s) {
    this.s = s;
  }
}

 

如果代码中没有明确编写构造函数,编译器会在编译期间隐式添加一个,如果一个类继承与其他类,那么父类的构造函数会被隐式调用。

下面的例子中不需要定义一个无参的空构造函数,如果类中没有定义构造函数,那么编译器会在编译期间为你定义一个构造函数:

MyConstructorExample.java:

public class MyConstructorExample {

  // unnecessary: would be created by the compiler if left out
  public MyConstructorExample() {
  }    
}

 

构造函数的命名约定是: classname (Parameter p1, ...) { }。每一个对象是基于构造函数创建的,构造函数是对象可以使用之前被调用的第一个方法。   


Virus.java

public class Virus {
    static int virusCount = 0;

    public Virus() {
        virusCount++;
    }

    static int getVirusCount() {
        return virusCount;
    }
}

VirusLab.java

public class VirusLab {
    public static void main(String[] args) {
        int numViruses = Integer.parseInt(args[0]);
        if (numViruses > 0) {
            Virus[] virii = new Virus[numViruses];
            for (int i = 0; i < numViruses; i++) {
                virii[i] = new Virus();
            }
            System.out.println("There are " + Virus.getVirusCount()
                + " viruses.");
        }
    }
}


修饰符(Modifiers)

访问控制修饰符

有三个用于访问控制的关键字: publicprotected 和 private

和 4 种访问控制级别:publicprotecteddefault 以及 private,这些级别用来定义元素对其他组件的可见性。

如果某些元素被声明为 public。比如:类或者方法,那么它们可以由其它 Java 对象创建或访问。如果某些元素被声明为 private,比如一个方法,那么这个方法就只能被定义它的类中的元素访问。

访问级别 protected 和 default 很相似,一个 protected 的类只能被同一个包中的类或者它的子类(同一个包或者其他包)访问,default 访问级别的类只能被同一个包中的类访问。

下表是访问级别的总结。    

表1. 访问级别

修饰符 子类 全局
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N

其他修饰符

  • final 方法:不可以被子类重写

  • abstracct 方法:抽象方法,没有实现的方法

  • synchronized 方法:线程安全的方法,可以是 final 方法以及赋予其他任何访问控制

  • native 方法:这种方法用来编写平台相关代码(比如:针对 Linux、Windows或Mac OS X等特定操作系统的本地代码)

  • strictfp: strictfp 关键字可应用于类、接口或方法。使用 strictfp 关键字声明一个方法时,该方法中所有的 float double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。当对一个类或接口使用 strictfp 关键字时,该类中的所有代码,包括嵌套类型中的初始设定值和代码,都将严格地进行计算。严格约束意味着所有表达式的结果都必须是 IEEE 754 算法对操作数预期的结果,以单精度和双精度格式表示。

 

import语句

使用 import 语句

在 Java 开发中我们需要使用类的全名来访问类,比如:cn.4byte.some_package.SomeClass。

你可以在类中使用 import 语句引入一些类或包,这样你在类中可以不用使用全名称来访问引入的类。

静态导入

static import 特性可以让我们在类中使用公共静态类( public static 定义的类)中的成员(方法、属性),而不需要在使用时指定定义成员的类。

该功能提供了一种类型安全的机制,让我们在代码中使用常量,而不必引用最初定义的常量的类。

更多的java语言结构        

类方法和类变量

与实例方法和实例变量不同,类方法和类变量是关联类的。需要使用 类名+'.'+方法名或变量名的方式访问类方法和类变量,如:SomeClass.someMethod 或者 SomeClass.someVariable

类方法和类变量需要使用 static 关键字来定义,类方法通常称为静态方法,类变量通常称为静态变量或者静态属性。

类变量的一个例子就是使用 System.out.println("Hello World") 调用 println 函数,这里的 out 就是一个静态域(静态变量),它是 PrintStream 的实例,我们通过它来调用 println 方法。

当你定义类变量后,Java 运行时环境在加载类时就会会为类变量分配固定的内存以及访问地址,因此无论类有多少个实例它的类变量始终指向相同的内存地址。我们可以将类变量理解为全局变量。下面的代码演示如何使用 static 域:

MyStaticExample.java    

public class MyStaticExample {
    
  static String PLACEHOLDER = "TEST";
      
  static void test() {
    System.out.println("Hello");
  }
}

Main.java:

public class Tester {
    
  public static void main(String[] args) {
    System.out.println(MyStaticExample.PLACEHOLDER);
    MyStaticExample.test();
  }
}

如果想要将变量定义为常量,可以使用 static final 关键字声明这个变量。

静态方法只能通过类来访问,不可以使用类的实例访问,它不能直接访问类中的非静态变量和方法。

抽象类和抽象方法

    类以及方法可以被声明为抽象的 abstract。如果一个类包含至少一个抽象方法(只有方法声明,没有方法实现)那么这个类就是一个抽象类,它也需要使用 abstract 关键字声明,并且这个类是不能够被直接实例化的。抽象类的子类需要实现抽象类中的抽象方法,除非子类也是抽象类。

    下面是抽象类定义的代码示例:

MyAbstractClass.java:

public abstract class MyAbstractClass {
  abstract double returnDouble();
}

类中类

下面Wrecker.java编译后生成 Wrecker.class和VirusCode.class。

public class Wrecker {
    String author = “Ignoto”;
    
    public void infectFile() {
        VirusCode vic = new VirusCode(1024);
    }
}

class VirusCode {
    int vSize;
    
    VirusCode(int size) {
        vSize = size;
    }
}

下面Wrecker.java编译后生成 Wrecker.class和Wrecker$VirusCode.class。

public class Wrecker {
    String author = “Ignoto”;
    
    public void infectFile() {
        VirusCode vic = new VirusCode(1024);
    }
    
    class VirusCode {
        int vSize;
        
        VirusCode(int size) {
            vSize = size;
        }
    }
}


备忘清单                    
    

使用类

在 Java 开发中你需要编写很多的类、方法、和实例变量,下面的代码使用 test 作为包名。

表格2 

What to do How to do it
创建MyNewClass类
package test;

public class MyNewClass {

}

创建 var1 变量

package test;

public class MyNewClass {
  private String var1;
}
创建构造函数,为 var1 赋值
package test;
public class MyNewClass {

  private String var1;
  
  public MyNewClass(String para1) {
    var1 = para1;
    // or this.var1= para1;
  }
}
创建doSomeThing方法
package test;
public class MyNewClass {

  private String var1;
  
  public MyNewClass(String para1) {
    var1 = para1;
    // or this.var1= para1;
  }
  
  public void doSomeThing() {
  }
}


创建doSomeThing2方法
package test;
public class MyNewClass {

  private String var1;
  
  public MyNewClass(String para1) {
    var1 = para1;
    // or this.var1= para1;
  }
  
  public void doSomeThing() {
  }
  
  public void doSomeThing2(int a, Person person) {
  }
}

创建doSomeThing3方法。

package test;
public class MyNewClass {

  private String var1;
  
  public MyNewClass(String para1) {
    var1 = para1;
    // or this.var1= para1;
  }
  
  public void doSomeThing() {
  }
  
  public void doSomeThing2(int a, Person person) {
  }
  
  public int doSomeThing3(String a, String b, Person person) {
    return 5; // any value will do for this example
  }
}
创建 MyOtherClass 类,以及两个属性 myvalue 和 dog及其set和get。
package test;
public class MyOtherClass {

  String myvalue;
  Dog dog;
  
  public String getMyvalue() {
    return myvalue;
  }
  
  public void setMyvalue(String myvalue) {
    this.myvalue = myvalue;
  }
  
  public Dog getDog() {
    return dog;
  }
  
  public void setDog(Dog dog) {
    this.dog = dog;
  }
}

this表示当前对象,这种方式引用变量可读性更好。

使用局部变量

局部变量只能在方法中定义

表格3

目的
实现
创建 String 类型的局部变量 String variable1;
创建 String 类型的局部变量,并赋值 "Test" String variable2 = "Test";
创建 Person 类型的局部变量 Person person;
创建 Person 类型的局部变量,并创建 Person 对象赋值给它 Person person = new Person();
创建字符串数组 String array[];
创建 Person 数组并指定数组长度为 5 Person array[]= new Person[5];
创建局部变量 var1 赋值 5 var1 = 5;
将 pers1 指向 pers2  pers1 = pers2;
创建 ArrayList 元素类型为 Person ArrayList<Person> persons;
创建新的 ArrayList 并赋值给 persons persons = new ArrayList<Person>();
创建 ArrayList 元素类型为 Person,并实例化 ArrayList<Person> persons = new ArrayList<Person>();

集成开发环境(IDE)

前面的章节介绍了如何在Shell(命令行)中创建和编译 Java 应用程序。 Java集成开发环境(IDE)提供了大量用于创建Java程序的易用功能。有很多功能丰富的 IDE 比如:Eclipse IDE                

更多的信息可以参考 教程。

术语 “创建一个 Java 项目(Create a Java project)”在这里可以理解为在 Eclipse 中创建一个 Java 项目。

练习:创建 Java 对象和方法

创建 Person 类并且实例化它

  • 创建一个 Java 项目叫 exercises1 并且使用 com.vogella.javastarter.exercises1 作为包名。

  • 创建 Person 类,并且为这个类增加三个实例变量:firstNamelastName 和 age

  • 使用Person的构造函数设置默认值。

  • 添加下面的toString方法并完善TODO内容,用于转换对象为字符串表示。

@Override
public String toString() {
    // TODO replace "" with the following:
    // firstName + " " + lastName
  return ""; 
}
  • 创建 Main 类,并定义方法 public static void main(String[] args),在这个方法中创建 Person 类的实例。

使用构造函数

为你的 Person 类添加构造函数,构造函数定义两个参数用来传递 first name 和 last name。并将这两个参数的值赋给对应的实例变量。

定义 getter 和 setter 方法    

定义用来读取和设置实例变量值的方法,这些方法被称为 getter 和 setter 方法。

Getter 方法命名方式是: get+实例变量名(实例变量名首字符需要大写)比如:  getFirstName()

Setter 方法命名方式是:set+实例变量名(实例变量名手字符需要大写)比如:setFirstName(String value)

修改 main 方法,使用 getter 和 setter 方法修改 Person 对象的 last name字段。

创建 Address 对象

创建Address 类用来保存 Person 的地址。    

        在 Person 对象中增加一个新的 Address 类型实例变量,以及对应的 getter 和 setter 方法。

答案:创建 Java 对象以及方法  

创建 Person 类并实例化

Person.java:

package exercises.exercise04;

class Person {

  String firstname = "Jim";
  String lastname = "Knopf";
  int age = 12;
          
  @Override
  public String toString() {
    return firstName + " " + lastName;
  }
}


Main.java:

package exercises.exercise04;
public class Main {

  public static void main(String[] args) {
    Person person = new Person();
    
    //  this calls the toString method on the pers object
    System.out.println(pers);
  }
}

使用构造函数    

package com.vogella.javastarter.exercises1;

class Person {

  String firstName;
  String lastName;
  int age;
  
  public Person(String a, String b, int value) {
    firstName = a;
    lastName = b;
    age=value;
  }
  
  @Override
  public String toString() {
    return firstName + " " + lastName;
  }
}

        

Main.java:

package com.vogella.javastarter.exercises1;
public class Main {

  public static void main(String[] args) {
  
    Person p1 = new Person("Jim", "Knopf" , 12);
    System.out.println(p1);
    // reuse the same variable and assign a new object to it
    Person p2 = new Person("Henry", "Ford", 104);
    System.out.println(p2);
  }
}


定义 getter 和 setter 方法

package com.vogella.javastarter.exercises1;

class Person {

  String firstName;
  String lastName;
  int age;
  
  public Person(String a, String b, int value) {
    firstName = a;
    lastName = b;
    age = value;
  }
  
  public String getFirstName() {
    return firstName;
  }
  
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  
  public String getLastName() {
    return lastName;
  }
  
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  
  public int getAge() {
    return age;
  }
  
  public void setAge(int age) {
    this.age = age;
  }
  
  @Override
  public String toString() {
    return firstName + " " + lastName;
  }
}


Main.java:

package com.vogella.javastarter.exercises1;

public class Main {

  public static void main(String[] args) {
  
    Person person = new Person("Jim", "Knopf", 21);
    Person p2 = new Person("Jill", "Sanders", 20);
    // Jill gets married to Jim
    // and takes his name
    p2.setLastName("Knopf");
    System.out.println(p2);
  }
}


创建 Address 对象

Address.java:

package com.vogella.javastarter.exercises1;

public class Address {

  private String street;
  private String number;
  private String postalCode;
  private String city;
  private String country;
  
  public String getStreet() {
    return street;
  }
  
  public void setStreet(String street) {
    this.street = street;
  }
  
  public String getNumber() {
    return number;
  }
  
  public void setNumber(String number) {
    this.number = number;
  }
  
  public String getPostalCode() {
    return postalCode;
  }
  public void setPostalCode(String postalCode) {
    this.postalCode = postalCode;
  }
  
  public String getCity() {
    return city;
  }
  
  public void setCity(String city) {
    this.city = city;
  }
  
  public String getCountry() {
    return country;
  }
  
  public void setCountry(String country) {
    this.country = country;
  }
  
  public String toString() {
    return street + " " + number + " " + postalCode + " " + city + " "
        + country;
  }
}

Person.java:

package com.vogella.javastarter.exercises1;

class Person {

  String firstName;
  String lastName;
  int age;
  private Address address;
  
  public Person(String a, String b, int value) {
    firstName = a;
    lastName = b;
    age=value;
  }
  
  public String getFirstName() {
    return firstName;
  }
  
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  
  public String getLastName() {
    return lastName;
  }
  
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  
  public int getAge() {
    return age;
  }
  
  public void setAge(int age) {
    this.age = age;
  }
  
  public Address getAddress() {
    return address;
  }
  
  public void setAddress(Address address) {
    this.address = address;
  }
  
  @Override
  public String toString() {
    return firstName + " " + lastName;
  }
}


Main.java:

package com.vogella.javastarter.exercises1;

public class Main {

  public static void main(String[] args) {
  
    // I create a person
    Person pers = new Person("Jim", "Knopf", 31);
    // set the age of the person to 32
    pers.setAge(32);

    // just for testing I write this to the console
    System.out.println(pers);
    /*
     * actually System.out.println always calls toString, if you do not
     * specify it so you could also have written System.out.println(pers);
     */
    // create an address
    Address address = new Address();
    // set the values for the address
    address.setCity("Heidelberg");
    address.setCountry("Germany");
    address.setNumber("104");
    address.setPostalCode("69214");
    address.setStreet("Musterstr.");

    // assign the address to the person
    pers.setAddress(address);

    // dispose reference to address object
    address = null;

    // person is moving to the next house in the same street
    pers.getAddress().setNumber("105");

  }

}

 

基础语句

if-then 和 if-then-else 语句

if-then 语句是控制语句,如果 if 部分表达式的结果为 true 将执行其定义的代码块。当 if 部分表达式结果为 false 则执行 else 代码块(若有的话)。

下面的代码演示了通过两个方法演示了 if-then 以及 if-then-else 语句:

class Game {
    public static void main(String[] arguments) {
        int total = 0;
        int score = 7;
        if (score == 7) {
            System.out.println("You score a touchdown!");
        }
        if (score == 3) {
            System.out.println("You kick a field goal!");
        }
        total = total + score;
        System.out.println("Total score: " + total);
    }
}

Switch

switch 语句是一个多条件选择执行语句简称开关语句,类似于 if-else语句。在 switch 的每一个分支里面都必须写 breakbreak 表示退出整个 switch语句,如果不使用 break 语句则当第一个 case 匹配后,会顺序执行后面的程序代码,而不管后面的 case 是否匹配,直到遇到 break语句为止,下面是 switch 语句的一个示例:

import java.util.*;

class Clock {
    public static void main(String[] arguments) {
        // get current time and date
        Calendar now = Calendar.getInstance();
        int hour = now.get(Calendar.HOUR_OF_DAY);
        int minute = now.get(Calendar.MINUTE);
        int month = now.get(Calendar.MONTH) + 1;
        int day = now.get(Calendar.DAY_OF_MONTH);
        int year = now.get(Calendar.YEAR);

        // display greeting
        if (hour < 12) {
            System.out.println("Good morning.\n");
        } else if (hour < 17) {
            System.out.println("Good afternoon.\n");
        } else {
            System.out.println("Good evening.\n");
        }

        // begin time message by showing the minutes
        System.out.print("It's");
        if (minute != 0) {
            System.out.print(" " + minute + " ");
            System.out.print( (minute != 1) ? "minutes" :
                "minute");
            System.out.print(" past");
        }

        // display the hour
        System.out.print(" ");
        System.out.print( (hour > 12) ? (hour - 12) : hour );
        System.out.print(" o'clock on ");

        // display the name of the month
        switch (month) {
            case 1:
                System.out.print("January");
                break;
            case 2:
                System.out.print("February");
                break;
            case 3:
                System.out.print("March");
                break;
            case 4:
                System.out.print("April");
                break;
            case 5:
                System.out.print("May");
                break;
            case 6:
                System.out.print("June");
                break;
            case 7:
                System.out.print("July");
                break;
            case 8:
                System.out.print("August");
                break;
            case 9:
                System.out.print("September");
                break;
            case 10:
                System.out.print("October");
                break;
            case 11:
                System.out.print("November");
                break;
            case 12:
                System.out.print("December");
        }

        // display the date and year
        System.out.println(" " + day + ", " + year + ".");
    }
}

 switch的后面可以带类型: character, an integer, or a string,后面要接break。 另外还有default。注意string在java7才支持。

public class Commodity {
    public static void main(String[] arguments) {
        String command = "BUY";
        int balance = 550;
        int quantity = 42;

        switch (command) {
            case "BUY":
               quantity += 5;
                balance -= 20;
                break;
            case "SELL":
                quantity -= 5;
                balance += 15;
        }
        System.out.println("Balance: " + balance + "\n"
            + "Quantity: " + quantity);
        }
}

布尔操作

使用 == 来比较两个原始类型是否相同或者比较两个引用类型是否指向同一个对象。使用 equals() 方法比较两个不同的对象是否相等。

&& 和 || 都是短路方法,意思是一旦表达        式中某个条件判断结果已经明确时,方法会停止不再执行后面的条件判断。比如:(true || ...) 结果始终是 true(false && ...) 结果始终是 false。使用示例:(var !=null     &&                     var.method1() ...)确保在调用 var.method1() 之前变量 var 始终不为 null

表4

Operations Description
== 比较,对于原始类型比较两个值,对于引用比较引用的对象地址
&&
!= 不等于
a.equals(b) 检查字符串 a 是否等于字符串 b
a.equalsIgnoreCase(b) 检查字符串 a 是否等于字符串 b,忽略大小写
If (value ? false : true) {} 三元操作,如果 value == true 返回 true

 

循环语句

for 循环

循环处理的语句。Java的for语句形式有两种:一种是和C语言中的for语句形式一样,另一种形式用于在集合和数组之中进行迭代。有时候把这种形式称为增强的 for(enhanced for) 语句,它可以使循环更加紧凑和容易阅读。它的一般形式为 for(;;) 语句; 初始化总是一个赋值语句,它用来给循环控制变量赋初值;条件表达式是一个关系表达式,它决定什么时候退出循环;增量定义循环控制变量每循环一次后            按什么方式变化。这三个部分之间用";"分开。例如:

for循环定义:

for(initialization; expression; update_statement)
{   //block of code to run 
}

示例语句:

public class ForTest {
  public static void main(String args[]) {
  for(int i = 1; i < 10; i = i+1) {
    System.out.println("value of i : " + i);
    }
  }
}

多个变量:

int i, j;
for (i = 0, j = 0; i * j < 1000; i++, j += 2) {
    System.out.println(i + “ * “ + j + “ = “ + (i * j));
}

初始化部分也可以为空。

for ( ; displayCount < endValue; displayCount++) {
    // loop statements would be here
}

 

While循环

while 循环语句是一个控制结构,可以重复的特定任务次数。在执行时,如果布尔表达式的结果为真,则循环中的动作将被执行,否则就跳出循环。

语法:

while(expression)
{  // block of code to run
}

示例:

public class WhileTest {

  public static void main(String args[]) {
  
    int x = 1;
    while (x < 10) {
      System.out.println("value of x : " + x);
      x++;
    }
  }
}

                

do-while 循环

do-while 循环与 while 循环非常类似,区别在于 while 循环先进行条件判断再开始循环,do-while 循环则是先循环在进行条件判断。

语法:

do{  
    // block of code to run
} while(expression);

示例:    

public class DoTest {
  public static void main(String args[]) {
    int x = 1;
    do {
      System.out.println("value of x : " + x);
      x++;
    } while (x < 10);
  }
}


循环命名适用于continue和break。

int points = 0;
int target = 100;
targetLoop:
while (target <= 100) {
    for (int i = 0; i < target; i++) {
        if (points > 50)
            break targetLoop;
        points = points + i;
    }
}

数组

数组是有序数据(同一类型数据)的集合,数组中的项称为元素,数组中的每个元素使用相同的数组名和下标来唯一地确定数组中的元素。数组中的第一个元素下标为 0,第二个元素下标为 1 ... 以此类推。

布尔类型在数组中默认值false,int默认值0,字符串 '\0',对象类型则默认为null。
长度:.length。

public class TestMain {
    public static void main(String[] args) {
        
        // declares an array of integers
        int[] array;
        
        // allocates memory for 10 integers
        array = new int[10];
                    
        // initialize values
        array[0] = 10;
        // initialize second element
        array[1] = 20;
        array[2] = 30;
        array[3] = 40;
        array[4] = 50;
        array[5] = 60;
        array[6] = 70;
        array[7] = 80;
        array[8] = 90;
        array[9] = 100;    
    }
}

 

字符串也可以当做数组处理:

class SpaceRemover {
    public static void main(String[] args) {
        String mostFamous = "Rudolph the Red-Nosed Reindeer";
        char[] mfl = mostFamous.toCharArray();
        for (int dex = 0; dex < mfl.length; dex++) {
            char current = mfl[dex];
            if (current != ' ') {
                System.out.print(current);
            } else {
                System.out.print('.');
            }
        }
        System.out.println();
    }
}

数组排序

import java.util.*;

class Name {
    public static void main(String[] args) {
        String names[] = { "Lauren", "Audrina", "Heidi", "Whitney",
            "Stephanie", "Spencer", "Lisa", "Brody", "Frankie",
            "Holly", "Jordan", "Brian", "Jason" };
        System.out.println("The original order:");
        for (int i = 0; i < names.length; i++) {
            System.out.print(i + ": " + names[i] + " ");
        }
        Arrays.sort(names);
        System.out.println("\nThe new order:");
        for (int i = 0; i < names.length; i++) {
            System.out.print(i + ": " + names[i] + " ");
        }
        System.out.println();
    }
}

注意:字符串和基础类型只能升序。

下面统计单词出现次数:

class Wheel {
    public static void main(String[] args) {
        String phrase[] = {
            "A STITCH IN TIME SAVES NINE",
            "DON'T EAT YELLOW SNOW",
            "JUST DO IT",
            "EVERY GOOD BOY DOES FINE",
            "I WANT MY MTV",
            "I LIKE IKE",
            "PLAY IT AGAIN, SAM",
            "FROSTY THE SNOWMAN",
            "ONE MORE FOR THE ROAD",
            "HOME FIELD ADVANTAGE",
            "VALENTINE'S DAY MASSACRE",
            "GROVER CLEVELAND OHIO",
            "SPAGHETTI WESTERN",
            "AQUA TEEN HUNGER FORCE",
            "IT'S A WONDERFUL LIFE"
        };
        int[] letterCount = new int[26];
        for (int count = 0; count < phrase.length; count++) {
            String current = phrase[count];
            char[] letters = current.toCharArray();
            for (int count2 = 0;  count2 < letters.length; count2++) {
                char lett = letters[count2];
                if ( (lett >= 'A') & (lett <= 'Z') ) {
                    letterCount[lett - 'A']++;
                }
            }
        }
        for (char count = 'A'; count <= 'Z'; count++) {
            System.out.print(count + ": " +
                letterCount[count - 'A'] +
                " ");
        }
        System.out.println();
    }
}

针对数组和容器增强的 for循环

可以使用下面更简单的 for 循环语句来遍历数组以及容器类,语法为:

for(declaration : expression)
{
  // body of code to be executed
}

用法示例:

    

public class TestMain {
    public static void main(String[] args) {
    
        // declares an array of integers
        int[] array;
    
        // allocates memory for 10 integers
        array = new int[10];
    
        // initialize values
        array[0] = 10;
        // initialize second element
        array[1] = 20;
        array[2] = 30;
        array[3] = 40;
        array[4] = 50;
        array[5] = 60;
        array[6] = 70;
        array[7] = 80;
        array[8] = 90;
        array[9] = 100;
    
        int idx = 0;
        for (int i : array) {
            System.out.println("Element at index " + idx + " :"  + i);
            idx++;
        }
    }
}

字符串

Java 中的字符串

Java 语言中使用 String 类来表示字符串,所有的字符串,如:"hello" 都是这个类的一个实例。字符串是不可变类型,比如:给String 对象赋新的值会创建一个新的 String 对    象。

Java 中的字符串池

Java 使用 String 池来提高字符串对象的内存使用效率。因为 Java 中字符串对象是不可变类型,因此字符串池允许重复使用已存在的字符串而不是每次都创建一个新的。

如果同一个字符串在 Java 代码中被多次使用,Java 虚拟机只会创建一个改字符串实例,并将其保存在字符串池中。

当一个 String 对象创建后,如:String s = "constant",字符串 "connstant" 会被保存在池中。不过,new 操作符会强制创建一个新的 String 对象拷贝,            并为它分配新的内存,比如:String s = new String("constant");

在 Java 中比较字符串

在 Java 中需要使用 equals() 来比较字符串对象,比如:s1.equals(s2)。使用 == 来比较字符串对象是不正确的,因为 == 是用来比较对象引用是否相同。由于 Java 使用字符串池,因此 == 在某些时候会给出正确的结果。

下面的例子将会得到正确的结果:

String a = "Hello";
String b = "Hello";
if (a==b) {
  // if statement is true
  // because String pool is used and
  // a and b point to the same constant
}

下面的比较会返回 false:          

String a = "Hello";
String b = new String("Hello");
if (a==b) {
  
} else {
                  // if statement is false
  // because String pool is used and 
  // a and b point to the same constant
}

警告:当进行字符串比较时,应该总是使用 equals() 方法。等于判断:favorite.equals(guess)。

长度计算:

String cinematographer = “Stuart Dryburgh”;
int nameLength = cinematographer.length();

字符串连接时,有一方是字符串,另一方可以转为字符串,这点比python要爽。

使用字符串


String是对象,首字母大写。
println()比print()多了换行

转义字符
\’ Single quotation mark
\” Double quotation mark
\\ Backslash
\t Tab
\b Backspace
\r Carriage return
\f Formfeed
\n Newline

下面的表格列出了常用的字符串方法

表格5:

Command Description
"Testing".equals(text1); 字符串对象 text1 的值等于 "Testing" 时返回 true
"Testing".equalsIgnoreCase(text1); 字符串对象 text1 的值等于 "Testing" 时返回 true。忽略大小写
StringBuffer str1 = new StringBuffer(); 声明并实例化一个 StringBuffer 对象
str.charat(1); 返回字符串中位置 1 的字符
str.substring(1); 删除第一个字符,只影响输出结果
str.substring(1, 5); 返回第2个至第5个字符
str.indexOf("Test") 在字符串中查找 "Test" 并返回位置
str.lastIndexOf("ing") 从后向前在字符串中查找 "ing" 并返回位置
str.endsWith("ing") 检查字符串是否以 "ing" 结尾                                                          
str.startsWith("Test") 检查字符串是否以 "Test" 开头
str.trim() 删除字符串前后的空格
str.replace(str1, str2) 将字符串中的 "str1" 替换为 "str2"
str2.concat(str1); 将 "str1" 拼接到 "str2" 尾部
str.toLowerCase()/str.toUpperCase() 转换字符串为小写或大写
str1 + str2 连接字符串

String[] array = myString.split("-");

String[] array2 = myString.split("\\.");

将字符串根据 "-" 分隔成字符串数组。注意分割内容部分是正则表达式。                       

 toUpperCase()  toLowerCase() 不会改变原字符串。indexOf() 找不到返回-1,否则返回索引。

class Credits {
    public static void main(String[] args) {
        // set up film information
        String title = "The Piano";
        int year = 1993;
        String director = "Jane Campion";
        String role1 = "Ada";
        String actor1 = "Holly Hunter";
        String role2 = "Baines";
        String actor2 = "Harvey Keitel";
        String role3 = "Stewart";
        String actor3 = "Sam Neill";
        String role4 = "Flora";
        String actor4 = "Anna Paquin";
        // display information
        System.out.println(title + " (" + year + ")\n" +
            "A " + director + " film.\n\n" +
            role1 + "\t" + actor1 + "\n" +
            role2 + "\t" + actor2 + "\n" +
            role3 + "\t" + actor3 + "\n" +
            role4 + "\t" + actor4);
    }
}


Lambda 表达式    

什么是 lambda 表达式

Java 编程语言从 Java 8 开始支持 lambda 表达式。Lambda 表达式是可以作为参数使用的一段代码。lambda 表达式允许指定的代码在稍后执行。Lambda 表达式    用于任何函数式接口适用的地方。

lambda 表达式和闭包的区别

lambda 表达式是一个匿名函数,比如:它可以作为参数定义。闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。这意味着闭包可以访问不在他参数列表中的变量,并且可以将闭包赋值给一个变量。

Java 支持 lambda 表达式,但不支持闭包。

引入 lambda 表达式的目的

使用 lambda 表达式比其他 Java 语法结构更加简洁,比如,Java 8 中 Collections 新增了一个 forEach 方法,这个方法可以接受 lambda 表达式,如下例:

List<String> list = new ArrayList<>();
list.add("vogella.com");
list.add("google.com");
list.add("heise.de");
list.forEach(System.out::println);

使用方法引用

在 lambda 表达式中可以使用方法引用,方法引用定义可以通过 CalledFrom::method 来调用的方法,CallFrom 可以是:

  • instance::instanceMethod

  • SomeClass::staticMethod

  • SomeClass::instanceMethod

比如下面代码:

List<String> list = new ArrayList<>();
list.add("vogella.com");
list.add("google.com");
list.add("heise.de");
list.forEach(s-> System.out.println(s));

流(stream)

Java 8 中的流(stream)是什么?

流(stream)是支持串行和并行聚合操作的元素序列。

新增加的Stream API (java.util.stream)引入了在Java里可以工作的函数式编程。这是目前为止对java库最大的一次功能添加,希望程序员通过编写有效、整洁和简明的代码,能够大大提高生产率。    

IntStream

用来创建支持串行和并行聚合操作的包含原始 int 类型的元素序列。下面演示的range和python的range很类似。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
public class IntStreamExample {
            
  public static void main(String[] args) {
  
    // printout the numbers from 1 to 100
    IntStream.range(1, 101).forEach(s -> System.out.println(s));
    
    // create a list of integers for 1 to 100
    List<Integer> list = new ArrayList<>();
    IntStream.range(1, 101).forEach(it -> list.add(it));
    System.out.println("Size " + list.size());
  }
}

 stream 和 lambda 的 Reduction 操作

Reduction 操作接受一个元素序列为输入,反复使用某个合并操作,把序列中的元素合并成一个汇总的结果,参考下面代码:

Task.java: 

public class Task {
    
      private String summary;
      private int duration;
      
      public Task(String summary, int duration) {
        this.summary = summary;
        this.duration = duration;
      }
      public String getSummary() {
        return summary;
      }
      public void setSummary(String summary) {
        this.summary = summary;
      }
      public int getDuration() {
        return duration;
      }
      public void setDuration(int duration) {
        this.duration = duration;
      }
      
}

 

StreamTester.java:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class StreamTester {
      public static void main(String[] args) {
      
            Random random = new Random();
            // Generate a list of random task
            List<Task> values = new ArrayList<>();
            IntStream.range(1, 20).forEach(i -> values.add(new Task("Task" + random.nextInt(10), random.nextInt(10))));
    
            
            // get a list of the distinct task summary field
            List<String> resultList = 
                  values.stream().filter(t -> t.getDuration() > 5).map(t -> t.getSummary()).distinct().collect(Collectors.toList());
            System.out.println(resultList);
            
            
            // get a concatenated string of Task with a duration longer than 5 hours
            String collect = 
                values.stream().filter(t -> t.getDuration() > 5).map(t -> t.getSummary()).distinct().collect(Collectors.joining("-"));
            System.out.println(collect);
      }
}

Optional    

如果你调用未初始化的字段或方法会收到    NullPointerException异常(NPE)。java.util.Optional类用于避免这些NPE。它通过方法的签名直接看到值是否存在,而不是通过javadoc返回null,它的 filter方法在没有值时返回空对象。该功能相当于把python默认值的一小部分学了过来,但是操作要复杂得多。

创建:

   

// use this if the object is not null
opt = Optional.of(o);
// creates an empty Optional, if o is null
opt = Optional.ofNullable(o);
// create an empty Optional
opt = Optional.empty();

ifPresent可以查看对象是否存在。          

Todo todo = new Todo(-1);
Optional<Todo> optTodo = Optional.of(todo);
// get the id of the todo or a default value 
optTodo.ifPresent(t-> System.out.println(t.getId()));

   

Todo todo = new Todo(-1);    
    Optional<Todo> optTodo = Optional.of(todo);
    // get the summary (trimmed) of todo if the id is higher than 0
    Optional<String> map = optTodo.filter(o -> o.getId() > 0).map(o -> o.getSummary().trim());  
    // same as above but print it out
    optTodo.filter(o -> o.getId() > 0).map(o -> o.getSummary().trim()).ifPresent(System.out::println);
// using a String
String s = "Hello";
Optional<String> maybeS = Optional.of(s);
// get length of the String or -1 as default
int len = maybeS.map(String::length).orElse(-1);
// orElseGet allows to construct an object / value with a Supplier
int calStringlen = maybeS.map(String::length).orElseGet(()-> "Hello".length());

实例:

import java.util.Optional;

public class Java8Tester {

   public static void main(String args[]){
   
      Java8Tester java8Tester = new Java8Tester();
      Integer value1 = null;
      Integer value2 = new Integer(10);
        
      //Optional.ofNullable - allows passed parameter to be null.
      Optional<Integer> a = Optional.ofNullable(value1);
        
      //Optional.of - throws NullPointerException if passed parameter is null
      Optional<Integer> b = Optional.of(value2);
      System.out.println(java8Tester.sum(a,b));
   }
    
   public Integer sum(Optional<Integer> a, Optional<Integer> b){
    
      //Optional.isPresent - checks the value is present or not
        
      System.out.println("First parameter is present: " + a.isPresent());
      System.out.println("Second parameter is present: " + b.isPresent());
        
      //Optional.orElse - returns the value if present otherwise returns
      //the default value passed.
      Integer value1 = a.orElse(new Integer(0));
        
      //Optional.get - gets the value, value should be present
      Integer value2 = b.get();
      return value1 + value2;
   }
}

类型转换(casting)

如果使用不同类型的变量,Java 需要进行显式类型转换,下面章节是一些例子。

转换为字符串

参考下面的代码将其他类型对象转换为字符串:            

// Convert from int to String
String s1 = String.valueOf (10); // "10" 
// Convert from double to String
String s2 = String.valueOf (Math.PI); // "3.141592653589793"
// Convert from boolean to String
String s3 = String.valueOf (1 < 2); // "true" 
// Convert from date to String
String s4 = String.valueOf (new Date()); // "Tue Jun 03 14:40:38 CEST 2003"

    

22.2 将字符串转换为数字

// Conversion from String to int
int i = Integer.parseInt(String);
// Conversion from float to int
float f = Float.parseFloat(String);
// Conversion from double to int
double d = Double.parseDouble(String);

从字符串到数字的转换独立于区域设置,比如:它总是使用数字的英语表示方法。在这种表示法中 "8.20" 是一个正确的数字,但德国藏用的 "8,20" 则是一个错误的数字。                

要转换类似于德国的数字表示,你需要使用 NumberFormat 类。我们面临的挑战是,当类似于 "98.00" 这类数字表示时, NumberFormat 会将其转换成 Long 而不是 Double。如果需要转换成 Double 请参考下面的方法,

private Double convertStringToDouble(String s) {

    Locale l = new Locale("de", "DE");
    Locale.setDefault(l);
    NumberFormat nf = NumberFormat.getInstance();
    Double result = 0.0;
    
    try {
      if (Class.forName("java.lang.Long").isInstance(nf.parse(s))) {
        result = Double.parseDouble(String.valueOf(nf.parse(s)));
      } else {
        result = (Double) nf.parse(new String(s));
      }
    } catch (ClassNotFoundException e1) {
      e1.printStackTrace();
    } catch (ParseException e1) {
      e1.printStackTrace();
    }         
    return result;
  }

 

22.3 Double 转换为 int

int i = (int) double;

22.4 SQL 日期类型转换

使用下面的类将 Date 类型转换为 SQL 的 Date类型

package test;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
    
public class ConvertDateToSQLDate {

    private void convertDateToSQL(){
       SimpleDateFormat template = 
          new SimpleDateFormat("yyyy-MM-dd"); 
          java.util.Date enddate = new java.util.Date("10/31/99"); 
          java.sql.Date sqlDate = java.sql.Date.valueOf(template.format(enddate)); 
       
    }
      public static void main(String[] args) {
        ConvertDateToSQLDate date = new ConvertDateToSQLDate();
        date.convertDateToSQL();
      }   
}

boolean ( Boolean class),  byte ( Byte ),  char ( Character ),  double ( Double ),
float ( Float ),  int ( Integer ),  long ( Long )和short ( Short )能自动装箱(Autoboxing)和自动拆箱(Unboxing)。

 下面代码在1.5以后不会报错。

Float total = new Float(1.3F);
float sum = total / 5;

计划任务

Java 支持计划任务,计划任务可以被执行一次或多次。

使用 java.util.Timer 和 java.util.TimerTask 来完成计划任务。实现 TimeTask 的对象将会由 Time 在指定的时间间隔执行。

MyTask.java:

package schedule;
import java.util.TimerTask;

public class MyTask extends TimerTask {

  private final String string;
  private int count = 0;
  
  public MyTask(String string) {
    this.string = string;
  }
  @Override
  public void run() {
    count++;
    System.out.println(string + " called " + count);
  }
}


ScheduleTest.java:

package schedule;
import java.util.Timer;
public class ScheduleTest {
  public static void main(String[] args) {
    Timer timer = new Timer();
    // wait 2 seconds (2000 milli-secs) and then start
    timer.schedule(new MyTask("Task1"), 2000);
    for (int i = 0; i < 100; i++) {
      // wait 1 seconds and then again every 5 seconds
      timer.schedule(new MyTask("Task " + i), 1000, 5000);
    }
  }
}

 提示:开源框架 "quartz" 提供了增强的计划任务功能。参考: http://www.onjava.com/lpt/a/4637 或 http://www.quartz-scheduler.org/


正则表达式

通配符

Regular Expression Description
. Matches any character
^regex Finds regex that must match at the beginning of the line.
regex$ Finds regex that must match at the end of the line.
[abc] Set definition, can match the letter a or b or c.
[abc][vz] Set definition, can match a or b or c followed by either v or z.
[^abc] When a caret appears as the first character inside square brackets, it negates the pattern. This pattern matches any character except a or b or c.
[a-d1-7] Ranges: matches a letter between a and d and figures from 1 to 7, but not d1.
X|Z Finds X or Z.
XZ Finds X directly followed by Z.
$ Checks if a line end follows.

元字符

Regular Expression Description
\d Any digit, short for [0-9]
\D A non-digit, short for [^0-9]
\s A whitespace character, short for [ \t\n\x0b\r\f]
\S A non-whitespace character, short for [^\s]
\w A word character, short for [a-zA-Z_0-9]
\W A non-word character [^\w]
\S+ Several non-whitespace characters
\b Matches a word boundary where a word character is [a-zA-Z0-9_].

These meta characters have the same first letter as their representation, e.g., digit, space, word, and boundary. Uppercase symbols define the opposite.

数量

Regular Expression Description Examples
* Occurs zero or more times, is short for {0,} X* finds no or several letter X, 
.* finds any character sequence
+ Occurs one or more times, is short for {1,} X+ - Finds one or several letter X
? Occurs no or one times, ? is short for {0,1}. X? finds no or exactly one letter X
{X} Occurs X number of times, {} describes the order of the preceding liberal \d{3} searches for three digits, .{10}for any character sequence of length 10.
{X,Y} Occurs between X and Y times, \d{1,4} means \d must occur at least once and at a maximum of four.
*? ? after a quantifier makes it a reluctant quantifier. It tries to find the smallest match. This makes the regular expression stop at the first match.


参考资料

英文地址:http://www.vogella.com/tutorials/JavaIntroduction/article.html

http://codex.wiki/post/165971-434

最佳实践的代码:http://javaboutique.internet.com/

 

微博 http://weibo.com/cizhenshi 作者博客:http://my.oschina.net/u/1433482 python测试开发精华群 291184506 PythonJava单元白盒测试 144081101


其他内容

参数处理

class BlankFiller {
    public static void main(String[] arguments) {
        System.out.println("The " + arguments[0]
            + " " + arguments[1] + " fox "
            + "jumped over the "
            + arguments[2] + " dog."
        );
    }
}

命令行执行:

# java BlankFiller hello new world
The hello new fox jumped over the world dog.

在NetBeans执行:
Run -> Project Configuration -> Customize, 输入BlankFiller,参数部分输入hello new world。
按F6或者Run -> run project。

Applet实例

Java程序设计简介_第4张图片

JApplet的行为和属性:
equals()
setBackground()
add()
setLayout()

import javax.swing.*;

public class SalutonFrame extends JFrame {
    public SalutonFrame() {
        super("Saluton mondo!");
        setLookAndFeel();
        setSize(350, 100);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        SalutonFrame sal = new SalutonFrame();
    }
}

上面的

super("Saluton mondo!");

设置了标题,也可以单独用方法设置:setTitle(“Main Frame”);

设置大小的另外一种方法是先填充,然后使用pack()。同时,默认会有合适的大小。

 setDefaultCloseOperation()的选项:JFrame.EXIT_ON_CLOSE、Frame.DISPOSE_ON_CLOSE、JFrame.DO_NOTHING_ON_CLOSE、JFrame.HIDE_ON_CLOSE。

java7引入的增强视觉方案引入方法:

UIManager.setLookAndFeel(
“com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel”
);

上述实例的效果如下:

Java程序设计简介_第5张图片

下面实例增加button:

import javax.swing.*;
import java.awt.*;

public class Playback extends JFrame {
    public Playback() {
        super("Playback");
        setLookAndFeel();
        setSize(225, 80);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        FlowLayout flo = new FlowLayout();
        setLayout(flo);
        JButton play = new JButton("Play");
        JButton stop = new JButton("Stop");
        JButton pause = new JButton("Pause");
        add(play);
        add(stop);
        add(pause);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        Playback pb = new Playback();
    }
}

效果如下:

CheckBoxes.java

import javax.swing.*;
import java.awt.*;

public class CheckBoxes extends JFrame {
    public CheckBoxes() {
        super("CheckBoxes");
        setLookAndFeel();
        setSize(195, 170);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JCheckBox jumboSize = new JCheckBox("Jumbo Size", true);
        JCheckBox frogLegs = new JCheckBox("Frog Leg Grande", true);
        JCheckBox fishTacos = new JCheckBox("Fish Taco Platter", false);
        JCheckBox emuNuggets = new JCheckBox("Emu Nuggets", false);
        FlowLayout flo = new FlowLayout();
        ButtonGroup meals = new ButtonGroup();
        meals.add(frogLegs);
        meals.add(fishTacos);
        meals.add(emuNuggets);
        setLayout(flo);
        add(jumboSize);
        add(frogLegs);
        add(fishTacos);
        add(emuNuggets);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        CheckBoxes cb = new CheckBoxes();
    }
}

执行效果:

Java程序设计简介_第6张图片

ClockPanel.java

import javax.swing.*;
import java.awt.*;
import java.util.*;

public class ClockPanel extends JPanel {
    public ClockPanel() {
        super();
        String currentTime = getTime();
        JLabel time = new JLabel("Time: ");
        JLabel current = new JLabel(currentTime);
        add(time);
        add(current);
    }

    final String getTime() {
        String time;
        // get current time and date
        Calendar now = Calendar.getInstance();
        int hour = now.get(Calendar.HOUR_OF_DAY);
        int minute = now.get(Calendar.MINUTE);
        int month = now.get(Calendar.MONTH) + 1;
        int day = now.get(Calendar.DAY_OF_MONTH);
        int year = now.get(Calendar.YEAR);

        String monthName = "";
        switch (month) {
            case (1):
                monthName = "January";
                break;
            case (2):
                monthName = "February";
                break;
            case (3):
                monthName = "March";
                break;
            case (4):
                monthName = "April";
                break;
            case (5):
                monthName = "May";
                break;
            case (6):
                monthName = "June";
                break;
            case (7):
                monthName = "July";
                break;
            case (8):
                monthName = "August";
                break;
            case (9):
                monthName = "September";
                break;
            case (10):
                monthName = "October";
                break;
            case (11):
                monthName = "November";
                break;
            case (12):
                monthName = "December";
        }
        time = monthName + " " + day + ", " + year + " "
            + hour + ":" + minute;
        return time;
    }
}

ClockFrame.java

import java.awt.*;
import javax.swing.*;

public class ClockFrame extends JFrame {
    public ClockFrame() {
        super("Clock");
        setLookAndFeel();
        setSize(225, 125);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        FlowLayout flo = new FlowLayout();
        setLayout(flo);
        ClockPanel time = new ClockPanel();
        add(time);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        ClockFrame clock = new ClockFrame();
    }
}

执行效果

Java程序设计简介_第7张图片

ComboBoxes.java 

import javax.swing.*;
import java.awt.*;

public class ComboBoxes extends JFrame {
    public ComboBoxes() {
        super("ComboBoxes");
        setLookAndFeel();
        setSize(345, 120);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JComboBox profession = new JComboBox();
        FlowLayout flo = new FlowLayout();
        profession.addItem("Butcher");
        profession.addItem("Baker");
        profession.addItem("Candlestick maker");
        profession.addItem("Fletcher");
        profession.addItem("Fighter");
        profession.addItem("Technical writer");
        setLayout(flo);
        add(profession);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        ComboBoxes cb = new ComboBoxes();
    }
}

执行效果:

Java程序设计简介_第8张图片

TextArea.java

import javax.swing.*;
import java.awt.*;

public class TextArea extends JFrame {
    public TextArea() {
        super("TextArea");
        setLookAndFeel();
        setSize(500, 190);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTextArea comments = new JTextArea(8, 40);
        FlowLayout flo = new FlowLayout();
        setLayout(flo);
        add(comments);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        TextArea ta = new TextArea();
    }
}

执行效果:

Java程序设计简介_第9张图片

TextField.java

import javax.swing.*;
import java.awt.*;

public class TextField extends JFrame {
    public TextField() {
        super("TextField");
        setLookAndFeel();
        setSize(375, 80);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel pageLabel = new JLabel("Web page address: ", JLabel.RIGHT);
        JTextField pageAddress = new JTextField(20);
        FlowLayout flo = new FlowLayout();
        setLayout(flo);
        add(pageLabel);
        add(pageAddress);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        TextField tf = new TextField();
    }
}

执行效果:

TwoFrames.java

import javax.swing.*;

public class TwoFrames extends JFrame {
    public TwoFrames() {
        super("First Frame");
        setSize(350, 100);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLookAndFeel();
        SecondFrame two = new SecondFrame();
        setVisible(true);
        two.setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        TwoFrames tf = new TwoFrames();
    }
}

class SecondFrame extends JFrame {
    SecondFrame() {
        super("Second Frame");
        setSize(150, 80);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}


import java.awt.*;

public class RootApplet extends javax.swing.JApplet {
    int number;

    public void init() {
        number = 225;
    }

    public void paint(Graphics screen) {
       Graphics2D screen2D = (Graphics2D) screen;
       screen2D.drawString("The square root of " +
           number +
           " is " +
           Math.sqrt(number), 5, 50);
    }
}

执行效果:

Java程序设计简介_第10张图片


基于FlowLayout的布局:

import java.awt.*;
import javax.swing.*;

public class Crisis extends JFrame {
    JButton panicButton;
    JButton dontPanicButton;
    JButton blameButton;
    JButton mediaButton;
    JButton saveButton;

    public Crisis() {
        super("Crisis");
        setLookAndFeel();
        setSize(348, 128);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        FlowLayout flo = new FlowLayout();
        setLayout(flo);
        panicButton = new JButton("Panic");
        dontPanicButton = new JButton("Don't Panic");
        blameButton = new JButton("Blame Others");
        mediaButton = new JButton("Notify the Media");
        saveButton = new JButton("Save Yourself");
        add(panicButton);
        add(dontPanicButton);
        add(blameButton);
        add(mediaButton);
        add(saveButton);
        setVisible(true);
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        Crisis cr = new Crisis();
    }
}

执行效果:


另外还有GridLayout、

GridLayout grid = new GridLayout(2, 3);
setLayout(grid);

BorderLayout:

BorderLayout crisisLayout = new BorderLayout();
setLayout(crisisLayout);
add(panicButton, BorderLayout.NORTH);
add(dontPanicButton, BorderLayout.SOUTH);
add(blameButton, BorderLayout.EAST);
add(mediaButton, BorderLayout.WEST);
add(saveButton, BorderLayout.CENTER);

BoxLayout(垂直布局):

JPanel pane = new JPanel();
BoxLayout box = new BoxLayout(pane, BoxLayout.Y_AXIS);
pane.setLayout(box);
pane.add(panicButton);
pane.add(dontPanicButton);
pane.add(blameButton);
pane.add(mediaButton);
pane.add(saveButton);
add(pane);

还可以指定位置插入:

Insets around = new Insets(10, 6, 10, 3);

布局实例:

import java.awt.*;
import javax.swing.*;

public class LottoMadness extends JFrame {

    // set up row 1
    JPanel row1 = new JPanel();
    ButtonGroup option = new ButtonGroup();
    JCheckBox quickpick = new JCheckBox("Quick Pick", false);
    JCheckBox personal = new JCheckBox("Personal", true);
    // set up row 2
    JPanel row2 = new JPanel();
    JLabel numbersLabel = new JLabel("Your picks: ", JLabel.RIGHT);
    JTextField[] numbers = new JTextField[6];
    JLabel winnersLabel = new JLabel("Winners: ", JLabel.RIGHT);
    JTextField[] winners = new JTextField[6];
    // set up row 3
    JPanel row3 = new JPanel();
    JButton stop = new JButton("Stop");
    JButton play = new JButton("Play");
    JButton reset = new JButton("Reset");
    // set up row 4
    JPanel row4 = new JPanel();
    JLabel got3Label = new JLabel("3 of 6: ", JLabel.RIGHT);
    JTextField got3 = new JTextField("0");
    JLabel got4Label = new JLabel("4 of 6: ", JLabel.RIGHT);
    JTextField got4 = new JTextField("0");
    JLabel got5Label = new JLabel("5 of 6: ", JLabel.RIGHT);
    JTextField got5 = new JTextField("0");
    JLabel got6Label = new JLabel("6 of 6: ", JLabel.RIGHT);
    JTextField got6 = new JTextField("0", 10);
    JLabel drawingsLabel = new JLabel("Drawings: ", JLabel.RIGHT);
    JTextField drawings = new JTextField("0");
    JLabel yearsLabel = new JLabel("Years: ", JLabel.RIGHT);
    JTextField years = new JTextField();

    public LottoMadness() {
        super("Lotto Madness");
        setLookAndFeel();
        setSize(550, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridLayout layout = new GridLayout(5, 1, 10, 10);
        setLayout(layout);

        FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER,
            10, 10);
        option.add(quickpick);
        option.add(personal);
        row1.setLayout(layout1);
        row1.add(quickpick);
        row1.add(personal);
        add(row1);

        GridLayout layout2 = new GridLayout(2, 7, 10, 10);
        row2.setLayout(layout2);
        row2.add(numbersLabel);
        for (int i = 0; i < 6; i++) {
            numbers[i] = new JTextField();
            row2.add(numbers[i]);
        }
        row2.add(winnersLabel);
        for (int i = 0; i < 6; i++) {
            winners[i] = new JTextField();
            winners[i].setEditable(false);
            row2.add(winners[i]);
        }
        add(row2);

        FlowLayout layout3 = new FlowLayout(FlowLayout.CENTER,
            10, 10);
        row3.setLayout(layout3);
        stop.setEnabled(false);
        row3.add(stop);
        row3.add(play);
        row3.add(reset);
        add(row3);

        GridLayout layout4 = new GridLayout(2, 3, 20, 10);
        row4.setLayout(layout4);
        row4.add(got3Label);
        got3.setEditable(false);
        row4.add(got3);
        row4.add(got4Label);
        got4.setEditable(false);
        row4.add(got4);
        row4.add(got5Label);
        got5.setEditable(false);
        row4.add(got5);
        row4.add(got6Label);
        got6.setEditable(false);
        row4.add(got6);
        row4.add(drawingsLabel);
        drawings.setEditable(false);
        row4.add(drawings);
        row4.add(yearsLabel);
        years.setEditable(false);
        row4.add(years);
        add(row4);
        
        setVisible(true);
    }
    
    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        LottoMadness frame = new LottoMadness();
    }
}

效果如下:

Java程序设计简介_第11张图片

组件的开启与关闭:

JButton previousButton = new JButton(“Previous”);
JButton nextButton = new JButton(“Next”);
JButton previousButton = new JButton(“Previous”);
JButton nextButton = new JButton(“Next”);

滚动条的构建


JSlider() 默认值50,范围0-100

JSlider(int, int)

JSlider(int, int, int) 最小、最大和默认值。


方向: JSlider.VERTICAL or  JSlider.HORIZONTAL

比如:

JSlider guess = new JSlider(JSlider.VERTICAL, 1, 1000, 500);


其他设置:

  setMajorTickSpacing(int)

  setMinorTickSpacing(int)

  

如下方式开启:

setPaintTicks(boolean)或setPaintLabels(boolean)。

ChangeListener接口可以改变事件:

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;

public class ColorSliders extends JFrame implements ChangeListener {
    ColorPanel canvas;
    JSlider red;
    JSlider green;
    JSlider blue;

    public ColorSliders() {
        super("Color Slide");
        setLookAndFeel();
        setSize(270, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        canvas = new ColorPanel();
        red = new JSlider(0, 255, 255);
        green = new JSlider(0, 255, 0);
        blue = new JSlider(0, 255, 0);

        red.setMajorTickSpacing(50);
        red.setMinorTickSpacing(10);
        red.setPaintTicks(true);
        red.setPaintLabels(true);
        red.addChangeListener(this);

        green.setMajorTickSpacing(50);
        green.setMinorTickSpacing(10);
        green.setPaintTicks(true);
        green.setPaintLabels(true);
        green.addChangeListener(this);

        blue.setMajorTickSpacing(50);
        blue.setMinorTickSpacing(10);
        blue.setPaintTicks(true);
        blue.setPaintLabels(true);
        blue.addChangeListener(this);

        JLabel redLabel = new JLabel("Red: ");
        JLabel greenLabel = new JLabel("Green: ");
        JLabel blueLabel = new JLabel("Blue: ");
        GridLayout grid = new GridLayout(4, 1);
        FlowLayout right = new FlowLayout(FlowLayout.RIGHT);
        setLayout(grid);
        
        JPanel redPanel = new JPanel();
        redPanel.setLayout(right);
        redPanel.add(redLabel);
        redPanel.add(red);
        add(redPanel);
        
        JPanel greenPanel = new JPanel();
        greenPanel.setLayout(right);
        greenPanel.add(greenLabel);
        greenPanel.add(green);
        add(greenPanel);
        
        JPanel bluePanel = new JPanel();
        bluePanel.setLayout(right);
        bluePanel.add(blueLabel);
        bluePanel.add(blue);
        add(bluePanel);
        add(canvas);
        
        setVisible(true);
    }

    public void stateChanged(ChangeEvent event) {
        JSlider source = (JSlider) event.getSource();
        if (source.getValueIsAdjusting() != true) {
            Color current = new Color(red.getValue(), green.getValue(),
                blue.getValue());
            canvas.changeColor(current);
            canvas.repaint();
        }
    }

    public Insets getInsets() {
        Insets border = new Insets(45, 10, 10, 10);
        return border;
    }
    
    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        ColorSliders cs = new ColorSliders();
    }
}

class ColorPanel extends JPanel {
    Color background;

    ColorPanel() {
        background = Color.red;
    }

    public void paintComponent(Graphics comp) {
        Graphics2D comp2D = (Graphics2D) comp;
        comp2D.setColor(background);
        comp2D.fillRect(0, 0, getSize().width, getSize().height);
    }

    void changeColor(Color newBackground) {
        background = newBackground;
    }
}

图片的创建


ImageIcon stopSign = new ImageIcon(“stopsign.gif”);

ImageIcon saveFile = new ImageIcon(“images/savefile.gif”);


使用

ImageIcon siteLogo = new ImageIcon(“siteLogo.gif”);

JLabel logoLabel = new JLabel(siteLogo);

ImageIcon searchWeb = new ImageIcon(“searchGraphic.gif”);

JButton search = new JTextField(searchWeb);


JButton refresh = new JButton(“Refresh”, “images/refreshIcon.gif”);


JToolBar()创建水平工具条

JToolBar(int),可以是水平(SwingConstants.HORIZONTAL)或者垂直(SwingConstants.HORIZONTAL)。

容器:BorderLayout

BorderLayout border = new BorderLayout();

pane.setLayout(border);

JToolBar bar = new JToolBar(SwingConstants.VERTICAL);

ImageIcon play = new ImageIcon(“play.gif”);

JButton playButton = new JButton(play);

ImageIcon stop = new ImageIcon(“stop.gif”);

JButton stopButton = new JButton(stop);

ImageIcon pause = new ImageIcon(“pause.gif”);

JButton pauseButton = new JButton(pause);

bar.add(playButton);

bar.add(stopButton);

bar.add(pauseButton);

add(bar, BorderLayout.WEST);

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Tool extends JFrame {
    public Tool() {
        super("Tool");
        setLookAndFeel();
        setSize(370, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // build toolbar buttons
        ImageIcon image1 = new ImageIcon("d:\\newfile.gif");
        JButton button1 = new JButton(image1);
        ImageIcon image2 = new ImageIcon("d:\\openfile.gif");
        JButton button2 = new JButton(image2);
        ImageIcon image3 = new ImageIcon("d:\\savefile.gif");
        JButton button3 = new JButton(image3);

        // build toolbar
        JToolBar bar = new JToolBar();
        bar.add(button1);
        bar.add(button2);
        bar.add(button3);

        // build text area
        JTextArea edit = new JTextArea(8, 40);
        JScrollPane scroll = new JScrollPane(edit);

        // create frame
        BorderLayout border = new BorderLayout();
        setLayout(border);
        add("North", bar);
        add("Center", scroll);
        setVisible(true);
    }

     private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }

    public static void main(String[] arguments) {
        Tool frame = new Tool();
    }
}


简单的applet实例:

import java.awt.*;
 
public class RootApplet extends javax.swing.JApplet {
    int number;
 
    public void init() {
        number = 225;
    }
 
    public void paint(Graphics screen) {
       Graphics2D screen2D = (Graphics2D) screen;
       screen2D.drawString("The square root of " +
           number +
           " is " +
           Math.sqrt(number), 5, 50);
    }
}

嵌入浏览器:

mport java.awt.*;

public class SalutonApplet extends javax.swing.JApplet {
    String greeting;

    public void init() {
        greeting = "Saluton mondo!";
    }

    public void paint(Graphics screen) {
        Graphics2D screen2D = (Graphics2D) screen;
        screen2D.drawString(greeting, 25, 50);
    }
}
<html>
<head>
<title>Saluton Mondo!</title>
</head>
<body bgcolor="#000000" text="#FF00FF">
<p>This is a Java applet.</p>
<applet
    code="SalutonApplet.class"
    codebase="..\\..\\build\\classes"
    height="150"
    width="300"
>
<p>You need a Java-enabled browser to see this.</p>
</applet>
</body>
</html>

参数传递:

import java.awt.*;

public class WeightScale extends javax.swing.JApplet {
    float lbs = 0F;
    float ozs;
    float kgs;
    float metricTons;
    String name = "somebody";

    public void init() {
        String lbsValue = getParameter("weight");
        if (lbsValue != null) {
            lbs = Float.valueOf(lbsValue);
        }
        String personValue = getParameter("person");
        if (personValue != null) {
            name = personValue;
        }
        ozs = (float) (lbs * 16);
        kgs = (float) (lbs / 2.204623);
        metricTons = (float) (lbs / 2204.623);
    }

    public void paint(Graphics screen) {
        Graphics2D screen2D = (Graphics2D) screen;
        screen2D.drawString("Studying the weight of " + name, 5, 30);
        screen2D.drawString("In pounds: " + lbs, 55, 50);
        screen2D.drawString("In ounces: " + ozs, 55, 70);
        screen2D.drawString("In kilograms: " + kgs, 55, 90);
        screen2D.drawString("In metric tons: " + metricTons, 55, 110);
    }
}

相应的HTML:

WeightScale.html

<applet code="WeightScale.class" codebase="..\\..\\build\\classes"
    height="170" width="210">
    <param name="person" value="Konishiki">
    <param name="weight" value="605">
</applet>

HTML5 要改用object标签

<applet code="WeightScale.class" codebase="..\\..\\build\\classes"
    height="170" width="210">
    <param name="person" value="Konishiki">
    <param name="weight" value="605">
</applet>

表达式的用途:更改变量的值;计数;使用数学公式。

Vector

Vector类似python的列表,长度可变。

import java.util.*;

public class StringLister {
    String[] names = { "Spanky", "Alfalfa", "Buckwheat", "Daria",
        "Stymie", "Marianne", "Scotty", "Tommy", "Chubby" };

    public StringLister(String[] moreNames) {
        Vector<String> list = new Vector<String>();
        for (int i = 0; i < names.length; i++) {
            list.add(names[i]);
        }
        for (int i = 0; i < moreNames.length; i++) {
            list.add(moreNames[i]);
        }
        Collections.sort(list);
        for (String name : list) {
            System.out.println(name);
        }
    }

    public static void main(String[] args) {
        StringLister lister = new StringLister(args);
    }
}


多线程

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class PrimeFinder extends JFrame implements Runnable, ActionListener {
    Thread go;
    JLabel howManyLabel;
    JTextField howMany;
    JButton display;
    JTextArea primes;

    PrimeFinder() {
        super("Find Prime Numbers");
        setLookAndFeel();
        setSize(400, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        BorderLayout bord = new BorderLayout();
        setLayout(bord);
       
        howManyLabel = new JLabel("Quantity: ");
        howMany = new JTextField("400", 10);
        display = new JButton("Display primes");
        primes = new JTextArea(8, 40);
        
        display.addActionListener(this);         
        JPanel topPanel = new JPanel();
        topPanel.add(howManyLabel);
        topPanel.add(howMany);
        topPanel.add(display);
        add(topPanel, BorderLayout.NORTH);
        
        primes.setLineWrap(true);
        JScrollPane textPane = new JScrollPane(primes);
        add(textPane, BorderLayout.CENTER);
        
        setVisible(true);
    }

    public void actionPerformed(ActionEvent event) {
        display.setEnabled(false);
        if (go == null) {
            go = new Thread(this);
            go.start();
        }
    }

    public void run() {
        int quantity = Integer.parseInt(howMany.getText());
        int numPrimes = 0;
        // candidate: the number that might be prime
        int candidate = 2;
        primes.append("First " + quantity + " primes:");
        while (numPrimes < quantity) {
            if (isPrime(candidate)) {
                primes.append(candidate + " ");
                numPrimes++;
            }
            candidate++;
        }
    }

    public static boolean isPrime(int checkNumber) {
        double root = Math.sqrt(checkNumber);
        for (int i = 2; i <= root; i++) {
            if (checkNumber % i == 0) {
                return false;
            }
        }
        return true;
    }

    private void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }
    public static void main(String[] arguments) {
        PrimeFinder fp = new PrimeFinder();
    }
}


基于Applet的多线程实例:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
public class LinkRotator extends JApplet
    implements Runnable, ActionListener {
    String[] pageTitle = new String[6];
    URL[] pageLink = new URL[6];
    Color butterscotch = new Color(255, 204, 158);
    int current = 0;
    Thread runner;
    public void init() {
        pageTitle = new String[] {
            "Sun's Java site",
            "Cafe au Lait",
            "JavaWorld",
            "Java in 24 Hours",
            "Sams Publishing",
            "Workbench"
        };
        pageLink[0] = getURL("http://java.sun.com");
        pageLink[1] = getURL("http://www.ibiblio.org/javafaq");
        pageLink[2] = getURL("http://www.javaworld.com");
        pageLink[3] = getURL("http://www.java24hours.com");
        pageLink[4] = getURL("http://www.samspublishing.com");
        pageLink[5] = getURL("http:// workbench.cadenhead.org");
        Button goButton = new Button("Go");
        goButton.addActionListener(this);
        FlowLayout flow = new FlowLayout();
        setLayout(flow);
        add(goButton);
    }
    URL getURL(String urlText) {
        URL pageURL = null;
        try {
            pageURL = new URL(getDocumentBase(), urlText);
        } catch (MalformedURLException m) { }
        return pageURL;
    }
    public void paint(Graphics screen) {
        Graphics2D screen2D = (Graphics2D) screen;
        screen2D.setColor(butterscotch);
        screen2D.fillRect(0, 0, getSize().width, getSize().height);
        screen2D.setColor(Color.black);
        screen2D.drawString(pageTitle[current], 5, 60);
        screen2D.drawString("" + pageLink[current], 5, 80);
    }
    public void start() {
        if (runner == null) {
            runner = new Thread(this);
            runner.start();
        }
    }
    public void run() {
        Thread thisThread = Thread.currentThread();
        while (runner == thisThread) {
            current++;
            if (current > 5) {
                current = 0;
            }
            repaint();
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // do nothing
            }
        }
    }
    public void stop() {
        if (runner != null) {
            runner = null;
        }
    }
    public void actionPerformed(ActionEvent event) {
        if (runner != null) {
            runner = null;
        }
        AppletContext browser = getAppletContext();
        if (pageLink[current] != null) {
            browser.showDocument(pageLink[current]);
        }
    }
}


文件读写


你可能感兴趣的:(Java程序设计简介)