java基础(3):第一个java程序

一、名字的可见性

    名字管理对任何程序设计语言来说,都是一个重要的问题。如果在程序的某个模块使用了一个名字,而其他人在这个程序的另一个模块里也使用了相同的名字,那么怎样才能区分这两个名字并防止二者互相冲突呢?

    java采用了一种全新的方法来避免上述所有问题。为了给一个类库生成不会与其他名字混淆的名字,java设计者希望程序员反过来使用自己的Internet域名,因为这样可以保证它们肯定是独一无二的。

    在java1.0和java1.1中,扩展名com、edu、org、net等约定为大写形式。然而,在java2开发到一半时,设计者们发现这样做会引起一些问题。因此,现在整个包名都是小写了。

    这种机制意味着所有的文件都能够自动存活于它们自己的名字空间内,而且同一个文件内的每个类都有唯一的标识符--java语言本身已经解决了这个问题。

二、运用其他构件

    如果想在自己的程序里使用预先定义好的类,那么编译器就必须知道怎么定位它们。当然,这个类可能就在发出调用的那个源文件中;在这种情况下,就可以直接使用这个类--即使这个类在文件的后面才会被定义。

    如果那个类位于其他文件中,又会怎样呢?你可能会认为编译器应该有足够的智慧,能够直接找到它的位置,但事实并非如此。想象下面的情况,如果你想使用某个特定名字的类,但其定义却不止一份(假设这些定义各不相同)。更糟糕的是,假设你正在写一个程序,在构建过程中,你想将某个新类添加到类库中,但却与已有的某个类名冲突。

    为了解决这个问题,必须消除所有可能的混淆情况。为实现这个目的,可以使用关键字import来准确的告诉编译器你想要的类是什么。import指示编译器导入一个包,也就是一个类库。

    大多时候,我们使用与编译器附在一起的java标准类库里的构件。有了这些构件,你就不必写一长串的反转域名。举例来说,只需向下面这么写就行了:

import java.util.ArrayList;

    这行代码告诉编译器,你想使用java的ArrayList类。但是,util包含了数量众多的类,有时候你想使用其中几个,同时又不想明确的逐一声明;那么你很容易使用通配符“*”来达到这个目的:

import java.util.*;

    这种一次导入一群类的方式比一个一个地导入类的方式更常用。

三、static关键字

    通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个类的对象,否则,实际上并未获得任何对象。执行new来创建对象时,数据存储空间才被分配,其方法才供外界调用。

    有两种情形用上述方法是无法解决的。一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象。另一种情形是,希望某个方法不与包含它的类的任何对象关联在一起。也就是说,即使没有创建对象,也能够调用这个方法。

    通过static关键字可以满足这两方面的需要。当声明一个事物是static时,就意味着这个域或方法不会与包含它的那个类的任何对象实例关联在一起。所以,即使从未创建某个类的任何对象,也可以调用其static方法或访问其static域。通常,你必须创建一个对象,并用它来访问数据或方法。因为非static域和方法必须知道它们一起运作的特定对象。

    有些面向对象语言采用类数据和类方法两个术语,代表那些数据和方法只是作为整个类,而不是类的某个特定对象而存在的。有时,一些java文献里也用到这两个术语。

    只需将static关键字放在定义之前,就可以将字段或方法设定为static。例如,下面的代码就生成了一个static字段,并对其进行了初始化:

class StaticTest{
		static int i = 47;
	}

    现在,即使你创建了两个StaticTest对象,StaticTest.i也只有一份存储空间,这两个对象共享同一个i。在看看下面代码:

StaticTest st1=new StaticTest();
StaticTest st2=new StaticTest();

    在这里,st1.i和st2.i指向同一存储空间,因为它们具有相同的值47。

    引用static变量有两种方法。如前例所示,可以通过一个对象去定位它,如st2.i;也可以通过其类名直接引用,而这对于非静态成员则不行。

StaticTest.i++;

    其中,++运算符对变量进行递加操作。此时,st1.i和st2.i仍具有相同的值48。

    使用类名是引用static变量的首选方式,这不仅是因为它强调了变量的static结构,而且在某些情况下它还为编译器进行优化提供了更好的机会。

    类似逻辑也应用于静态方法。既可以像其他方法一样,通过一个对象来引用某个静态方法,也可以通过特殊的语法形式ClassName.method()加以引用。定义静态方法的方式与定义静态变量的方式相似:

class Incrementable {
	static void increment() {
		StaticTest.i++;
	}
}

   可以看到,Incrementable的increment()方法通过++运算符将静态数据i递加。可以采用典型的方式,通过对象来调用increment():

Incrementable sf =new Incrementable();
sf.increment();

     或者,因为increment()是一个静态方法,所以也可以通过它的类直接调用:

Incrementable.increment();

    尽管当static作用于某个字段时,肯定会改变数据创建的方式(因为一个static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象又一个存储空间),但是如果static作用于某个方法,差别却没有这么大。static方法的一个重要用法就是在不创建任何对象的前提下就可以调用它。正如我们将会看到的那样,这一点对定义main()方法很重要,这个方法是运行一个应用时的入口点。

    和其他任何方法一样,static方法可以创建或使用与其类型相同的被命名对象,因此,static方法常常拿来做“牧羊人”的角色,负责看护与其隶属同一类型的实例群。

四、第一个java程序

    让我们来编写第一个完整的程序。此程序开始是打印一个字符串,然后是打印当前日期,这里用到了java标准库里的Date类。

import java.util.Date;

public class HelloDate {
	public static void main(String[] args) {
		System.out.println("你好, 今天是:");
		System.out.println(new Date());
	}
}

    在每个程序文件的开头,必须声明import语句,以便引入在文件代码中需要用到的额外类。注意,在这里说它们“额外”,是因为有一个特定类会自动被导入到每一个java文件中:java.lang。由于java.lang是默认导入到每个java文件中的,所以它的所有类都可以被直接使用。java.lang里没有Date类,所以必须导入另外一个类库才能使用它。

    java.lang.System类有许多属性,可以看到out是一个静态的PrintStream对象。

public final static PrintStream out = null;

    因为是静态的,所以不需要创建任何东西,out对象便已经存在了,直接使用即可。但我们能够用out对象做什么事情,是由它的类型PrintStream决定的。PrintStream类的println()方法,它的实际作用是“将我给你的数据打印到控制台,完成后换行”。因此,在任何java程序中,一旦需要将某些数据打印到控制台,就可以这样写:

System.out.println("A String of things");

    类的名字必须和文件名相同。如果你像现在这样创建一个独立运行的程序,那么文件中必须存在某个类与该文件同名(否则,编译器会报错),且那个类必须包含一个名为main()的方法,形式如下所示:

public static void main(String[] args) {}

    其中,public关键字意指这是一个可由外部调用的方法。main()方法的参数是一个String对象的数组。在这个程序中并未用到args,但是java编译器要求必须这么做,因为args要用来存储命令行参数。

System.out.println(new Date());

    在这里,传递的参数是一个Date对象,一旦创建它之后,就可以直接将它的值(它被自动转换为String类型)发送给println()。当这条语句执行完毕后,Date对象就不再被使用,而垃圾回收器发现这一情况,并在任意时候将其回收。因此,我们就没有必要去关心怎么清理它了。

    当你阅读JDK文档或查看源码时,将会发现System有许多其他的方法,使得你可以去创造很多有趣的效果(java最强大的优势之一就是它具有庞大的标准类库集)。例如:

public class ShowProperties {
	public static void main(String[] args) {
		System.getProperties().list(System.out);
		System.out.println(System.getProperty("user.name"));
		System.out.println(System.getProperty("java.library.path"));
	}
}

    main()的第一行将显示从运行程序的系统中获取的所有“属性”,因此它可以向你提供环境信息。list()方法将结果集发送给它的参数:System.out。你还可以询问具体的属性,例如在本例中,我们查询了用户名和java.library.path。

发布了71 篇原创文章 · 获赞 2 · 访问量 6161

猜你喜欢

转载自blog.csdn.net/qq_40298351/article/details/103969397