欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Class(二)

程序员文章站 2022-07-16 21:23:02
...

静态域和静态方法

静态域

public class Employee {
    private static int nextId = 1;
    private  int id;
    private static double  name = 1;
}

其中nextId和name变量用static修饰,即成为静态域。这个类和这个类所有的对象共享同一个值,他在内存中只存在一份,严格来说在每个jvm只存在一份。即使类没有实例化,这个域也存在。这个域属于类,而不属于对象。
即每个Employee对象都有一个id的拷贝,他们的值各不相同,所有的Employee对象都共享nextId和name。

静态常量

使用关键字 static final修饰的为静态常量

public class Employee {
    private static final int MONEY = 11;
}

静态常量可以用通过类访问,即Employee.MONEY访问。由于每个类对象都可以对公有域进行更改,所以最好不要讲域设计为public。但是用final修饰则无妨,final修饰则无法更改。

静态方法

静态方法是一种不能向对象实施操作的方法。例如Math类中的pow方法就是一个静态方法。表达式:Math.pow(x,a)
在运算时,不使用任何Math对象,即没有隐式参数(没有this参数)。
Employee类的静态方法不能访问Id实例域, 因为它不能操作对象。但是,静态方法可以访问自身类中的静态域。

public static int getNextld()
{
return nextld; // returns static field 
}

可以通过类名.方法名访问,即Employee.getNextld()。
这个方法可以省略关键字 static吗? 答案是肯定的。但是, 需要通?过Employee类对象的 引用调用这个方法。
可以使用对象调用静态方法,但是不建议
在下面两种情况下使用静态方法:

  • 方法不需要访问对象状态, 其所需参数都是通过显式参数提供(例如: Math.pow ) 。
  • 方法只需要访问类的静态域(例如: Employee.getNextld)

工厂方法

使用静态工厂方法构造对象。例如:NumberFormat类使用如下工厂方法生成不同风格的格式化对象。

NumberFormat currencyFormatter = NumberFormat.getCurrencylnstance(); 
NumberFormat percentFormatter = NumberFormat.getPercentlnstance();
double x = 0.1; System.out.println(currencyFormatter.format(x)); // prints $0.10
System.out.println(percentFomatter.format(x)); // prints 10%

为什么 NumberFormat 类不利用构造器完成这些操作呢? 这主要有两个原因:

  • 无法命名构造器。 构造器的名字必须与类名相同。但是, 这里希望将得到的货币实例和百分比实例采用不用的名字。
  • 当使用构造器时, 无法改变所构造的对象类型。 而 Factory 方法将返回一个 DecimalFormat类对象, 这是 NumberFormat 的子类

main方法

main方法也是一个静态方法,其不对任何方法进行操作。事实上,程序启动时还没有任何一个对象。静态的main方法将执行并创建程序所需要的对象。

方法参数

Java总是按值传递参数的,方法得到的是所有参数值的一个拷贝, 特别是,方法不能修改传递给它的任何参数变量的内容。
此处争议颇多,我会单独拿出来详细学习一下。
下面总结一下 Java 中方法参数的使用情况:

  • 一个方法不能修改一个基本数据类型的参数 (即数值型或布尔型)。
  • 一个方法可以改变一个对象参数的状态
  • 一个方法不能让对象参数引用一个新的对象。

对象构造

重载

类有多个构造器,每个构造器名字相同,但是参数不同,这就是重载。当然重载不仅仅适用于构造器。要完整地描述一个方法,需要指出方法名和参数类型,这就叫做方法的签名。返回类型不是方法签名的一部分,即不能有着方法名,参数类型相同,但返回类型不同的两个方法。

默认域初始化

如果在构造器没有显式地给域赋初值,则会自动地赋默认值:数值为0,布尔值为false,对象引用为null。
这是域与局部变量主要的不同点,必须明确地初始化方法中的局部变量。

无参构造器

如果在编写一个类时没有编写构造器, 那么系统就会提供一个无参数构造器。 这个构造 器将所有的实例域设置为默认值。 于是, 实例域中的数值型数据设置为 0、 布尔型数据设置 为 false、 所有对象变量将设置为 nul。l
如果类中提供了至少一个构造器, 但是没有提供无参数的构造器, 则在构造对象时如果 没有提供参数就会被视为不合法。

调用另一个构造器

this关键字通常用于:参数变量用同样的名字将实例域屏蔽起来。实例如下:

public Employee(String name, double salary)
{
this.name = name;
this,salary = salary; 
}

然而这个关键字还有另一个含义。
如果构造器的第一个语句形如 this(…), 这个构造器将调用同一个类的另一个构造器。 下 面是一个典型的例子:

public Employee(double s) {
// calls Employee(String, double) 
this("Employee #" + nextld, s); 
nextld++;
}

当调用 new Employee(60000) 时, Employee(double) 构造器将调用 Employee(String,double) 构造器。
采用这种方式使用 this 关键字非常有用, 这样对公共的构造器代码部分只编写一次 即可。

初始化块

前面已经讲过两种初始化数据域的方法:

  • 在构造器中设置值
  • 在声明中赋值

实际上, Java 还有第三种机制, 称为初始化块(initializationblock )。 在一个类的声明中, 可以包含多个代码块。只要构造类的对象, 这些块就会被执行

class Employee
{
private static int nextld;
private int id; 
private String name; 
private double salary;
// object initialization block
{
id = nextld; 
nextld++;
}
public Employee(String n, double s) {
name = n;
salary = s;
}
public Employee() {
name = "";
salary = 0;
}

在这个示例中, 无论使用哪个构造器构造对象,id 域都在对象初始化块中被初始化。首先运行初始化块,然后才运行构造器的主体部分
即使在类的后面定义, 仍然可以在初始化块中设置域。但是, 为了避免循环定义, 不要读取在后面初始化的域。 因此建议将初 始化块放在域定义之后。
由于初始化域途径很多,所以总结一下调用构造器具体步骤:

  1. 所有数据域被初始化为默认值(0、 false 或 null )。
  2. 按照在类声明中出现的次序, 依次执行所有域初始化语句和初始化块。
  3. 如果构造器第一行调用了第二个构造器, 则执行第二个构造器主体
  4. 执行这个构造器的主体.

可以通过提供一个初始化值, 或者使用一个静态的初始化块来对静态域进行初始化。

  • private static int nextld = 1;
  • // static initialization block static
    {
    Random generator = new Random();
    nextld = generator.nextlnt(10000);
    }

在类第一次加载的时候, 将会进行静态域的初始化。与实例域一样, 除非将它们显式地设置成其他值, 否则默认的初始值是 0、 false 或 nul。l 所有的静态初始化语句以及静态初始 化块都将依照类定义的顺序执行。

导入

import 语句不仅可以导入类, 还增加了导入静态方法和静态域的功能。

包作用域

前面已经接触过访问修饰符 public 和 private。 标记为 public 的部分可以被任意的类使用;标记为private的部分只能被定义它们的类使用。如果没有指定public或private, 这个部分(类、 方法或变量)可以被同一个包中的所有方法访问。

类路径

后面单独学习