2.1
2.2使用预先定义的类
封装
在java编码中,类是很重要的。比如Day1提到的Math类,我们可以使用该类里面的方法,比如说Math.random()而不用知道他们是如何实现的。我们只需要知道该方法的名字和所需要的参数即可。
这种将方法存放于类中的操作在java中我们称之为封装。
对象和对象变量
当我们需要调用一个对象的时候,我们首先要做的是构造他们。
在Java中,我们使用构造器来创建(构造)一个对象。
构造器是一种特殊的方法,其目的是构造并初始化一个对象。
由构造器创建的对象和直接定义并给予其类型和初始化的对象变量有很大区别:
Date deadline; // 此时,deadline的值为null
deadline = new Date();
如上代码所示,deadline在这里被称作对象变量,而 new Date() 这个整体代码创建了一个对象。可以理解为对象变量是对象的中转站,对象变量指向对象所存储的位置。
PS:又提到了存储位置,那么也就是说,如果此时有另外一个对象变量用“=”复制了原对象变量,那么两者将指向的都是同一个对象。
2.3定义你自己的类
现在我们来自己定义属于我们自己的类。通常一个类拥有属于其自身的实例字段和方法。
以下是一个简单的类形式:
class Rectangle{
private double length,width; //实例字段
Rectangle(){}
Rectangle(double l,double w){ //构造器---特殊方法
length = 1;wideth = w;
}
public double area() { return lenth*width; } //方法
public double perimeter(){
return (length+width)*2;
}
}
使用多个源文件
在用eclipse编写java程序的过程中,我们会遇到以下情况:
由于public类名要和java的文件文件名保持一致,所以一个java文件中有且只能有一个public类(也可以没有),但是可以同时拥有其他多个类。
因此,在编写程序的过程中,为了降低程序相互之间的依赖性,我们最好将每个文件放在属于他们自己的源文件中。
构造器
什么是构造器,我们已经在上文中提到过,其本质上是为了方便调用对应类的方法。那么该如何定义并使用构造器,让我们看到上述代码的这一段:
Rectangle(){}
Rectangle(double l,double w){
length = 1;wideth = w;
}
很容易可以看出构造器的创建规则:
1.构造器的名称必须与所在类的名称完全相同
2.一个类中可以有超过一个的构造器
3.一个构造器可以接受0,1或者更多的参数
4.一个构造器不能有返回值,也不用定义返回值类型
当一个构造器需要接收一个或多个参数时,我们称之为参数构造器;当一个构造器不接收任何参数时,我们称之为无参构造器。
当一个类中没有明写任何构造器时,代码默认其内部包含一个无参构造器;
当一个类中已经写有一个构造器(不论是否有参数),代码内此时有且仅有这一个构造器;
当我们使用new关键字来调用构造器时,构造器运作并创建对象:
public class RectangleTest{
public stativ void main(String[] args){
Rectangle rt1 = new Rectangle(); //调用构造器
Rectangle rt2 = new Rectangle(5,6);
}
}
请注意:
构造器能且只能被new调用并创建对象
PS:在一个类中,如果存在字段的定义出现在构造器知前,那么当开始运行程序时,这谢字段的定义会在构造器被new创建之前执行。
隐式参数和显式参数
public void raiseSalary(double byPercent){
double raise = salary * byPercent / 100;
salary += rasie;
}
上述代码中,byPercent就是显参,salary就是隐参。他们唯一的区别就是是否在方法内明写出对于该参数的定义(隐参就是在方法外部定义过了直接拿来用)。也就是局部变量(显参)和全局变量(隐参)的区别
在每个方法中,关键字this常用于指向隐参。这这样可以清楚的区分实例字段和局部变量。当然,一般来说写与不写并不会影响代码的正常运行,但是!如果隐参与显参的名字完全相同,那么this关键字一定不能少!不然会造成指代不明导致程序数据引用出错。
public void raiseSalary(double salary){
double raise = this.salary * byPercent / 100;
this.salary += rasie;
}
封装对写属于自己的类的好处
让我们在所写的Ractangle类中增加几行小代码:
class Rectangle{
private double length,width;
Rectangle(){}
Rectangle(double l,double w){
length = 1; width = w;
}
public double getLength(){ return lenth; } //新增四句
public double getWidth(){ return width; }
public double setLength(double length){
this.length = length;
}
public double setWidth(double width){
this.width = width;
} //到这里为止
public double area() { return lenth*width; }
public double perimeter(){
return (length+width)*2;
}
}
位于上方的两个get方法被称为字段访问器(field accessor)。由于实例字段length和width被关键字private修饰,外部类无法直接调用该字段从而获取其字段值,这时候get方法就起到中转战的作用,使外部类中的对象通过调用get方法获取类中的私有(private)字段值。
问:为什么不直接将priavte改为public从而使外部类能够直接调用Rectangle内字段呢?
首先,这涉及到程序的安全性的问题,在应用中可能会导致内部数据泄露;其次,这破坏了封装。在编写代码时应该避免这种情况发生。
位于下方的两个set方法被称为字段赋值器(filed mutator)。与访问器相反,该方法的作用是根据外部所给的参数修改类内部的字段。
私有priavte
当我们创建一个类时,我们会将所有的实例字段用private修饰以保证内部数据的安全。同样的,一个方法也可以施加同样的操作。其目的与私有化实例字段类似,这里就不再赘述。
在代码编写中,应当分清字段或方法的作用和使用场合,合理的使用public或private进行修饰
final关键字
当某个数据已经被确定,不需要进行修改或一系列操作时,我们可以在存储这个数据的实例字段前
添加关键字final进行修。
被final修饰的对象变量(实例字段)可以被调用,但其内布置一定不可以进行修改
2.4静态字段和方法
在接触java的第一个程序的时候,我们应该注意到了主方法main被关键字static修饰。这个关键字代表“静态的”。下面将对该关键字进行一个详细的解析:
静态字段
class Employee{
private static int nextId = 0;
private int id = 0;
//以下代码省略,包括构造器,set和get方法
}
如上图所示代码为例。如果我在主方法中用new生成100个Employee类的对象,那么此时,在计算机内部将会存在100个关于id的实例字段,但是,只会存在一个nextId 字段。
被static修饰的字段可以参加任何修改和调用,但所有修改都作用在同一个地址的对象上
下面是对应上方Employee代码的应用代码实例以及运行结果:
//以下代码默认写在主类内部
public static void main(String[] args){
Employee e1 = new Employee();
Employee e2 = new Employee();
Employee e3 = new Employee();
e1.changeId(); //changeId方法,作用是id+1
e2.changeId();
e3.changeId();
e1.changeNextid(); //changeNextid方法,作用是nextId+1
e1.changeNextid();
e1.changeNextid();
System.out.print(e1.getId());
System.out.print(e1.getNextid());
}
运行玩完整代码后,得到的是e1e2e3的id值为1,二他们的nextId值为3。应证了上面所述。
static和final对比
final | static |
值不可以被修改 | 值可以被修改 |
存储地址的多少根据创建对象数变化 | 只有一个存储地址 |
可以被调用 | 可以被调用 |
静态常数
相对于静态变量而言,静态常数在编码过程中会使用的更为频繁。像数学中的π,物理中某种物质的密度ρ这中已经规定好大小的数据,因为其数据的唯一性和固定性,在Java中通常以静态常数的方式储存,将会同时用到final和static两个关键字。
public class Math{
public static final double PI = 3.1415926;
//以下代码省略
}
静态方法
被static修饰的方法叫做静态方法。关于使用静态方法有以下要求:
静态方法只能调用和返回静态字段
值得一提的是,普通方法既可以调用和返回一般字段,也可以调用和返回静态字段。那么为什么不只使用普通方法呢?
原因很简单,staic方法在程序启动之初就已经是一个实例对象了,不需要通过new创建对象来调用,而是直接可以通过类名.方法名()的方式直接调用!
例子就是第一天提到的Math类库中的方法例如pow等,都可以Math.pow()直接使用。
2.5方法的参数
在编码过程中,有两种方法的参数:实际参数(实参)和形式参数(形参)。
假设这是一段Samp类里的方法:
public static double Sample(double x){
x = x*3;
return x;
}
现在,让我们在main函数中写一串代码来调用这个方法:
double precent = 10;
precent = Samp.Sample(precent); //运用到刚讲过的类名直接调用静态方法
在这两段代码中,在main函数中的precent(准确的说是Sample方法括号中的)就是实际参数,而Samp类中Sample方法后括号内的x则是形式参数。
实际参数和形式参数的关系可以这么解释:
对于实际参数,代码在运作的时候会自动开辟一块地址用于存储其值。但是形式参数相当于一个替身,用到的时候被创建,接收实际参数的值并代替其进行一系列操作,并会在程序终止时自动销毁。
2.6对象构造
重载Overloading
当某些类中需要用到多个构造器时,比如:
StringBuilder messages = new StringBuider();
StringBuilder todoList = new StringBuilder("To go");
这时,第二个对于StringBuilder类对象的创建就叫做重载。
字段的默认初始值
在Java中,当我们创建一个字段但没有初始化该字段的值时,由于每个字段都有对应的类型,所以java会对其赋予一个默认值:
数字类(int,double等)为0,boolean为false,其他引用类型为null
PS;除了基本类型之外,调用你所创建的任意类构造器所生成的对应类的对象的类型均被称为引用类型(包括String,数组这些java开发者写好的在类库中已经存在的引用类型)。
构造器的自我调用
当需要在构造器中调用自身的时候,我们需要用到this关键字
public Employee(double s){
this("Employee #"+nextId,s);
nextId++;
}
2.7包Package
Java允许我们将多个类集中放在packge(包)内。标准的Java库中包含许多的包,包括java.lang,java.util,java.net等等。那么这么做有什么好处呢?
在同一个包内,java允许所有类使用自己或者其他类中的方法
只要在所写的java程序头部写上这样一段代码,即可使用其中全部非private方法和字段:
import java.引用包的名字.*;