1、方法
一个类可以拥有多个方法,方法可以有四种不同的访问修饰符修饰。
一个类的方法大致可以分为两种:
- 普通方法
- 构造方法
# 普通方法
普通方法的语法:
修饰符 方法返回类型 方法名(参数类型 参数1 , 参数类型 参数2 , .....) {
若干方法语句;
return 方法返回值;
}
eg:假如HaC我有一辆车,车的名字是AE86
public class Car {
public String carName;
public void printCarName() {
System.out.println("车的名字:" + carName);
}
}
class HaC {
public static void main(String[] args) {
Car car = new Car();
car.carName = "HaC的AE86";
car.printCarName();
}
}
输出:
车的名字:HaC的AE86
以上printName()
就是 普通方法了。
但是有个问题:每次去初始化carName
,都是通过car.carName = "HaC的AE86";
的方法,HaC
这个类只是一个调用者,而这个carName
本应该是属于Car
类所有,我不需要知道你有什么属性,我只需要打印我的车名字就够了。
既然这样,就修改一下代码:
public class Car {
private String carName; //改成 private ,外部就不能访问了
public void printCarName() {
System.out.println("车的名字:" + carName);
}
public void setCarName(String carName) {
this.carName = carName; //this 表示本实例
}
}
class HaC {
public static void main(String[] args) {
Car car = new Car();
car.setCarName("AE86");
car.printCarName();
}
}
现在Car
这个类只提供setCarName()
的方法初始化 carName
,只保留方法给外部调用,这就是面向对象的三大特性之一——封装。
简单的说就是通过set、get 方法或者指定的方法去获取值
# 封装
将一类事物的属性和行为抽象成一个类,一般是使其属性私有化,行为公开化,提高了数据的隐秘性的同时,使代码模块化。这么做的好处是:
将变化隔离
便于使用
提高安全性
封装原则:
- 将不需要对外提供的内容都隐藏起来
- 把属性都隐藏,提供公共方法对其访问
# this变量
在方法内部,可以定义一个隐含的变量 this
,执行当前实例。
private String carName;
public void setCarName(String carName) {
this.carName = carName; //this 表示本实例,this必不可少
}
this.carName
是只全局变量(方法外面的变量)
后面的carName
是参数的carName
在 局部变量和全局变量重名,那么局部变量优先级更高,要使用全局变量就必须加上this
# 可变参数
我的车可能不止一个名字,那咋办?
那直接修改setCarName()
方法的参数就好了,
public class Car {
private String carName;
public void printCarName() {
System.out.println("车的名字:" + this.carName);
}
public void setCarName(String carName) {
this.carName = carName;
}
public void setCarName(String carName1, String carName2) {
this.carName = carName1 + "," + carName2;
}
}
class HaC {
public static void main(String[] args) {
Car car = new Car();
car.setCarName("豆腐神车AE86","排水渠神车AE86");
car.printCarName();
}
}
但是这种方法很麻烦啊,因为我不知道以后还会不会多起几个名字,岂不是要写很多个方法?
duck不必,Java中有支持可变参数
eg:
public class Car {
private String carName;
public void printCarName() {
System.out.println("车的名字:" + this.carName);
}
public void setCarName(String... names) { //可变参数
String carName = "";
for (int i = 0; i < names.length; i++) { // names 其实是一个数组
carName += names[i] + ","; //拼接carName的名字
}
this.carName = carName.substring(0, carName.length() - 1); //String字符串的 substring API方法,表示截取 0~n 位
}
}
class HaC {
public static void main(String[] args) {
Car car = new Car();
car.setCarName("豆腐神车AE86", "排水渠神车AE86", "改装版AE86");
car.printCarName();
}
}
输出:
车的名字:豆腐神车AE86,排水渠神车AE86,改装版AE86
# 构造函数
每次设置一个carName,我都要调用car.setCarName("AE86");
,这种方法实在太麻烦了。
创建实例对象的时候,能不能一起把所有的变量都初始化了呢?
答案是可以的,只需要定义 构造函数
构造函数语法:
类名 (参数类型 参数1 , 参数类型 参数2 , .....) {
若干方法语句;
}
构造方法没有返回类型、返回参数
eg:
public class Car {
private String carName;
public Car(String carName) { //构造函数
this.carName = carName;
}
public void printCarName() {
System.out.println("车的名字:" + this.carName);
}
}
class HaC {
public static void main(String[] args) {
Car car = new Car("AE86"); //直接调用构造函数,不用set方法了
car.printCarName();
}
}
输出:
车的名字:HaC的AE86
构造方法也可以调用自身的构造方法,使用 this
即可
eg:
class Car {
private String carName;
private int carAge;
public Car(String carName, int carAge) {
this.carName = carName;
this.carAge = carAge;
}
public Car(String carName) {
this(carName, 0); // 调用另一个构造方法Car(String, int)
}
public Car() {
this("Unnamed"); // 调用另一个构造方法Car(String)
}
}
如果调用new Car("AE86", 2);
,会自动匹配到构造方法Car(String carName, int carAge)
。
如果调用new Car("AE86");
,会自动匹配到构造方法public Car(String carName)
。
如果调用new Car();
,会自动匹配到构造方法public Car()
。
如果没有声明构造函数,会自动生成一个无参的构造函数。
即
public Car() {
}
# 方法重载
方法固然是很多的,但是同一个功能的方法,名字能不能相同呢?
答案是可以的,只需要修改 参数列表 即可,在Java中,又叫 重载。
重载是面向对象实现多态的其中一种方式之一,重载实现的是编译时的多态性(编译就确定调用哪个方法)。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;
重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
eg:
public class Car {
private String carName;
public Car(String carName) {
this.carName = carName;
}
public void printCarName() {
System.out.println("车的名字:" + this.carName);
}
public void printCarName(int carAge) {
System.out.println("车的名字:" + this.carName + ",车龄:" + carAge);
}
public void printCarName(int carAge, int kilometre) {
System.out.println("车的名字:" + this.carName + ",车龄:" + carAge + ",公里数:" + kilometre);
}
}
class HaC {
public static void main(String[] args) {
Car car = new Car("AE86");
car.printCarName();
car.printCarName(3);
car.printCarName(3, 100000);
}
}
输出:
车的名字:AE86
车的名字:AE86,车龄:3
车的名字:AE86,车龄:3,公里数:100000
printCarName()
就是重载了,有三种不同的参数列表。