Java基础教程(10)--类
一.声明类
你已经见过了以如下方式定义的类:
class MyClass {
  // field, constructor, and method declarations
}
上面是声明类的最基本的语法。可以在声明类时提供更多的信息,例如它继承的父类,或实现的接口等,例如:
class MyClass extends MySuperClass implements MyInterface {
    // field, constructor, and method declarations
}
  这意味着MyClass类继承自MySuperClass类并是实现了MyInterface接口。
  还可以在开头加上修饰符,例如public、private、final等。有关这些修饰符的作用将在下文中进行详细的介绍。一般来说,类声明由以下几部分组成:
- 修饰符。例如public、private以及其他将会在后面见到的修饰符;
 - 类名。按照惯例使用首字母大写的驼峰命名法。
 - 继承的父类。使用关键字extend声明,一个类只能直接继承一个父类。
 - 一个或多个实现的接口。使用关键字implements声明,多个接口之间使用逗号隔开。
 - 类体。定义在一对大括号中。
 
二.域的声明
Bicycle类使用以下几行代码声明它的域:
public int cadence;
public int gear;
public int speed;
域的声明由以下几部分组成:
- 修饰符,例如private、public、static、final等;
 - 域的类型;
 - 域的名称。
 
权限修饰符
权限修饰符用来控制其他类对一个成员的访问权限。现在我们只讨论public和private,其他权限修饰符将在后面的文章中介绍。
- public:可以从所有类访问该字段;
 - private:只能在自己的类中访问。
 
本着封装的精神,应该尽可能地将域的访问权限设为private,这意味这只能在自己的类中访问它的值。但是,其他类仍有访问它的需要,可以通过添加访问域的方法来供其他类访问,就像下面这样:
public class Bicycle {
    private int cadence;
    private int gear;
    private int speed;
    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }
    public int getCadence() {
        return cadence;
    }
    public void setCadence(int newValue) {
        cadence = newValue;
    }
    public int getGear() {
        return gear;
    }
    public void setGear(int newValue) {
        gear = newValue;
    }
    public int getSpeed() {
        return speed;
    }
    public void applyBrake(int decrement) {
        speed -= decrement;
    }
    public void speedUp(int increment) {
        speed += increment;
    }
}
三.定义方法
下面定义了一个方法:
public int add(int a, int b) {
    return a + b;
}
方法定义中必需的是返回值类型,方法名,一对小括号,以及大括号和方法体。更一般地来说,方法的声明由六个部分组成:
- 修饰符——例如public、private、static等;
 - 返回值类型——方法返回的数据的类型。若方法无返回值则为void;
 - 方法名称——和变量的命名规则相同,但惯例有一点不同;
 - 参数列表——位于小括号中,用逗号隔开。方法也可以没有参数;
 - 方法抛出的异常——有关这部分的内容将在后续教程中进行介绍;
 - 方法体——位于大括号中,方法的具体代码。
 
签名:方法的签名由方法名称和参数列表组成。签名用来在一个类中唯一地标识一个方法,也就是说,一个类中不能存在两个签名相同的方法。上面的add方法的签名为add(int a, int b)。
方法的名称可以是任何合法的标识符。但是按照惯例,方法名的第一个单词应该是动词并且小写它的首字母。例如run、compareTo等。
方法的重载
  重载是指一个类中的两个或多个方法具有相同的名称但具有不同的参数列表。Java支持方法的重载,并且可以通过方法的签名区分它们。
  假设有一个计算器类Calculator。为不同类型的操作数的加法设计不同的名字是一件很麻烦的事,例如addInt、addDouble、addFloat等。在Java中,可以为这些方法使用相同的名称,只要它们的参数列表是不同的。例如:
public class Calculator {
    public static add(int a, int b) {return a + b;}
    public static add(double a, double b) {return a + b;}
    ...
}
不能声明名称和参数列表都相同的方法,因为编译器无法区分它们。编译器在区分方法时只考虑签名,所以名称和参数列表相同,但返回值不同的两个方法并不算重载,编译器将会给出错误。
四.构造器
构造器(也称构造方法)是将类实例化为对象是自动调用的方法。但与普通方法不同的是,它的名字与类名相同且没有返回值。例如,Bicycle类有一个构造方法:
public Bicycle(int startCadence, int startSpeed, int startGear) {
    gear = startGear;
    cadence = startCadence;
    speed = startSpeed;
}
在创建对象时,new运算符将会调用构造方法:
Bicycle myBike = new Bicycle(30, 0, 8);
一个类可以有多个构造方法,只要它们的参数列表不同。还可以有无参构造方法:
public Bicycle() {
    gear = 1;
    cadence = 10;
    speed = 0;
}
  如果没有提供构造方法,编译器将会自动提供一个无参构造方法,这个无参构造方法会自动调用父类的无参构造方法。如果父类没有无参构造方法,编译器将会给出错误。因此在不提供构造方法时要保证父类有无参构造方法。如果你的类没有明确的父类,那么它有一个隐含的父类Object,这个类有一个无参构造方法。
  可以在构造方法中手动调用父类的构造方法,有关这部分的内容将会在接口和继承的教程中介绍。还可以在构造方法的声明中使用访问修饰符来控制哪些类可以调用构造函数。如果某个类不能调用本类的构造方法,则无法在该类内部直接创建本类对象。
五.向方法或构造器传递参数
方法的参数分为形式参数和实际参数。形式参数(简称形参)是方法声明中的参数列表,实际参数(简称实参)是指在调用方法时传递的具体的值。调用方法时,实际参数的顺序和类型必须与形式参数完全匹配。例如之前定义的add方法:
int add(int a, int b) {
    return a + b;
}
下面的语句调用了这个方法并把返回值赋值给变量sum,2和3就是调用方法时传递的实参:
int sum = add(2, 3);
还可以传递任意数量的参数。例如让add方法可以计算任意数量的整数的和:
int add(int... a) {
    int sum = 0;
    for(int i = 0; i < a.length; i++) {
        sum += a[i];
    }
    return sum;
}
  可以看到,在方法内部,这个参数被视为一个数组,可以通过数组的访问形式去访问每一个参数。需要注意的是,参数列表中只能有一个这样的参数,并且它必须放在最后一个位置上。
  形参的名称如果与类的某个域的名称相同,那么在这个方法内,这个形参将会屏蔽与它同名的域。可以使用this关键字来区分同名的形参和域,有关this关键字的内容将会在后面的文章中讨论。
基本数据类型参数
基本数据类型的参数按值传递到方法中。这意味着对参数值的任何更改都仅存在于方法的范围内。方法返回时,参数消失,对它们的任何更改都将丢失。下面是一个例子:
public class PassPrimitiveByValue {
    public static void main(String[] args) {
        int a = 1;
        increment(a);
        System.out.println(a);
    }
    public static void increment(int x) {
        x = x + 1;
    }
}
这个程序会输出1而不是2。x只是接收了a的值,对x的操作与a完全没有关系,所以函数结束后,a的值还是1。
引用类型参数
引用类型的参数将引用传递到方法中。对形参的操作就相当于对实参进行同样的操作。例如:
public class PassPrimitiveByReference {
    public static void main(String[] args) {
        Foo foo = new Foo(1);
        changeBar(foo);
        System.out.println(foo.getBar());
    }
    public static void changeBar(Foo f) {
        f.setBar(2);
    }
}
class Foo {
    private int bar;
    public Foo(int bar) {this.bar = bar;}
    public int getBar() {return bar;}
    public void setBar(int bar) {this.bar = bar;}
}
这个程序会输出2。因为形参f和实参foo引用了同一个对象。
Java基础教程(10)--类的更多相关文章
- Java基础教程——BigDecimal类
		
BigDecimal类 float.double类型的数字在计算的时候,容易发生精度丢失. 使用java.math.BigDecimal类可以解决此类问题. 前面讲过Math类,现在的BigDecim ...
 - Java基础教程——Date类和Calendar类
		
Date类和Calendar类都是关于日期的类,都在java.util包中,使用时需要import. Date java.util.Date类的对象用来表示时间和日期,用得最多的是获取系统当前日期和时 ...
 - Java基础教程——Math类
		
Math Java这种级别的编程语言怎么可能没有数学相关的操作呢? java.lang.Math类提供了基本数学运算的方法. 该类是final的,说明不能被继承. 该类的构造方法是私有的(privat ...
 - Java基础教程——File类、Paths类、Files类
		
File类 File类在java.io包中.io代表input和output,输入和输出. 代表与平台无关的文件和目录. 可以新建.删除.重命名,但不能访问文件内容. File类里的常量: impor ...
 - Java基础教程——Scanner类
		
Scanner属于java.util包. java.util包是Java内置的一个工具包,其中包含一系列常用的工具类,如处理日期.日历.集合类: 如果要使用到该包中的类,必须显式引入包名:import ...
 - Java基础教程——RunTime类
		
RunTime类 java.lang.RunTime类代表Java程序的运行时环境. 可以进行垃圾回收(gc()),可以进行系统资源清理(runFinalization()): 可以加载文件(load ...
 - Java基础教程——System类
		
System类 java.lang.System类代表当前Java程序的运行平台. |-可以做输入输出,垃圾回收:(此处不讲) |-可以获取时间: |-可以获取环境变量: |-可以获取系统信息: |- ...
 - Java基础教程——Object类
		
Object类 Object类是Java所有类类型的父类(或者说祖先类更合适) <Thinking in Java(Java编程思想)>的第一章名字就叫"everything i ...
 - Java基础教程——String类
		
String类 Java程序中的所有字符串字面值(如 "abc" )都是String的实例 字符串是常量(因为 String 对象是不可变的,所以可以共享) 字符串的本质是字符数组 ...
 
随机推荐
- SFML从入门到放弃(3) 视角和碰撞检测
			
SFML从入门到放弃(3) 视角和碰撞检测 视角 window.draw();所画出的对象是在世界坐标的绝对位置. 视角可以选定在窗口中显示世界坐标下的的哪一个区域. sf::View init_vi ...
 - P3175 [HAOI2015]按位或
			
传送门 一如既往膜拜shadowice巨巨 前置姿势我就没一个会的-- //minamoto #include<bits/stdc++.h> #define R register #def ...
 - Mac 设置终端中使用 sublime 打开文件
			
在Mac下用终端创建文件等比较方便,但如果配合Sublime用,最好是可以直接在终端中输入命令就可以用Sublime打开指定文件或文件夹. #检查用户目录下有没有bin目录,如里没有就创建一个(目的是 ...
 - fluentd 推送 mariadb audit log
			
说明: mariadb audit log是 mariadb 的审计日志 目的是把日志拆分成 tab 键分隔的字段 直接附上 fluentd 配置文件 <system> log_level ...
 - ssh密钥认证排错
			
sshd配置文件没问题: 目录权限设置也没问题: 但是 ssh -vvv 提示: debug3: no such identity: /Users/user/.ssh/id_rsa,/Users/us ...
 - 双向一对一映射@OneToOne
			
双向一对一的实例我已经上传到GitHub,entrance项目上了,感兴趣的可以下载下来跑跑,这里讲两个在运行过程中遇到的问题. 问题一:上一篇博客的最后我留下了问题.一对一关联查询注解@OneToO ...
 - linux安装应用程序
			
实验:为 Linux 主机安装应用程序 环境:vmware workstation 14 . redhad-server-6.4 需求:1.使用 RPM 包的方式安装 Mozilla Firef ...
 - openerp学习笔记 视图样式(表格行颜色、按钮,字段只读、隐藏,按钮状态、类型、图标、权限,group边距,聚合[合计、平均],样式)
			
表格行颜色: <tree string="请假单列表" colors="red:state == 'refuse';blue:state = ...
 - 剑指offer四十九之把字符串转换成整数
			
一.题目 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 二.思路 详见代码. 三.代码 public class Solution { ...
 - 【转】linux下杀死进程(kill)的N种方法
			
转载一篇,最原始的出处已不可考,望见谅! 常规篇: 首先,用ps查看进程,方法如下: $ ps -ef ……smx 1822 1 0 11:38 ? 00:00:4 ...