Write In Front
个人主页:令夏二十三
欢迎各位→点赞 + 收藏⭐️ + 留言
系列专栏:Java
总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
目录
1. 基础概念
1.1 类
1.2 字段和方法
2. 方法
类是组成Java程序的基本要素,作为一类对象的原型,它封装了这类对象的状态和方法,实际上就是把变量和函数封装到一个类里面。
字段(field)是类的属性,其实就是变量,字段又称为域、域变量、属性和成员变量等。
方法(method)是类的功能和操作,是用函数来表示的。
下面就是一个名为Person的类,其中包含了字段和方法:
class Person {
String name;
int age;
void sayHello () {
System.out.println ("Hello! My name is " + name);
}
}
通俗意义上理解,“人类”可以定义为一个类(class),而具体的人就是实例(instance)。
因此,完全可以把class看作一种数据类型,instance就是根据class创建的实例,这些实例肯定多包含类定义中的所有字段和方法,但是不同实例的具体字段可以不相同。下面就是介绍类和实例的代码示例:
package Liao;
class City {
public String name; // 用public修饰可以使得这个字段可以被同软件包中的所有类调用
public double latitude;
public double longitude;
}
public class ACityTest {
public static void main (String[] args) {
City gz = new City (); //创建一个实例,用变量gz指向它
gz.name = "Guangzhou";
gz.latitude = 23.13;
gz.longitude = 113.27;
System.out.println (gz.name);
System.out.println("location: " + gz.latitude + "°, " + gz.longitude + "°");
}
}
方法是定义在class中的操作,可以看作是一个函数,方法前面加上不同修饰标识符会有不同效果:
方法前加上 | 效果 |
public | 使得该方法可以被同文件中的所有类调用 |
private | 该方法只能被class中的其他方法调用 |
如果方法的形参名和类的字段名相同,则在方法内使用字段的时候,必须使用this来区分开;
在调用方法时,若有参数,必须严格填写参数,此外,还可以设置非法输入的提示语句。
下面是一个计算年龄的示例:
package Liao;
import java.util.*;
class Body {
private String name;
private int birth;
public void setName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("invalid input!"); // 非法提示 }
this.name = name;
}
public void setBirth(int birth) {
if (birth < 0 || birth > 2023) {
throw new IllegalArgumentException("invalid input!");
}
this.birth = birth;
}
public String getName() {
return name;
}
public int getBirth() {
return this.birth;
}
public int getAge() {
return calcAge(2023);
}
private int calcAge(int currentYear) {
return currentYear - this.birth;
}
public void replyBody(String name, int birth) {
System.out.printf("Hi %s, I'm very glad to tell you that you are really %d years old!", name, getAge());
}
}
public class BMethodTest2 {
public static void main(String[] args) {
Body B = new Body();
Scanner scanner = new Scanner(System.in);
System.out.print("Please input your name: ");
String name = scanner.next();
System.out.println();
B.setName(name);
System.out.print("Please enter your birth year: ");
int birth = scanner.nextInt();
B.setBirth(birth);
System.out.println();
System.out.printf("Hello %s, you are %d years old.", B.getName(), B.getAge());
System.out.println();
B.replyBody(B.getName(), B.getBirth());
}
}
当方法的参数为数组时,参数值可以传递,对于数组参数,其格式较为特殊,见下例:
package Liao;
import java.util.*;
class Group {
private String[] names;
private int[] ages;
public void setAges(int[] ages) {
this.ages = ages;
}
public void setNames(String... names) {
this.names = names;
}
public String getName(int i) {
return this.names[i-1];
}
}
public class BMethodTest3 {
public static void main(String[] args) {
Group g = new Group();
g.setNames("Tom", "Jane", "Andy");
System.out.printf("Please enter the index: ");
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt();
System.out.print(g.getName(i));
g.setAges(new int[] {17, 18, 19});
}
}
从上面的代码中可以知道,方法的参数为数组时,直接写一般格式需要在调用时新建一个数组,如果用 “...” 来代替方括号,则可以直接往调用的括号里填数据元素值,无论填多少都可以,这时候的数组是动态的。
一般来说,我们使用一个类来创建实例后,接下来要给实例赋值,如果实例的field是public的,那么可以直接赋值,如果是private的,就得使用类里面定义的set方法来赋值了。
这样赋值的话,效率很低,因为对每个field赋值都得写一条语句,那么有没有方法一句就把值都赋了呢?当然有了,这就需要构造方法派上用场了。
构造方法其实就是在类里面定义的赋值方法,它和所在的类同名,而且没有返回值,这两个特点就足以知道它有多重要了。在构造方法的参数列表中,可以写上与我们想要赋值的field的数据类型相同的形参,在方法的函数体里就可以用this对它们逐一赋值了;
那怎么使用构造方法呢?其实和我们使用类创建实例一模一样,只不过在使用构造方法创建实例时,括号里面就得写上想要给字段赋的值了。这不仅让我们浮想联翩,为什么会一样呢?实际上,当我们定义一个类但没有写构造方法时,系统就默认产生一个构造方法,只不过这个方法没有参数,所以我们一开始用类创建对象时,用的就是默认的构造方法!
如果我们定义了一个带参数的构造方法后,那这个方法就变成默认的了,这时候想要使用原先的无参数构造方法,就需要我们在类定义里面再写一个空的构造方法;
同时,构造方法也是可以有很多种的,它们名字都必须和类同名,但是参数列表可以不一样,当我们使用不同参数的构造方法时,系统会自动匹配,特别智能!而且不同的构造方法间也可以相互调用,只不过使用时要用this来代替名字,也要使用正确的调用格式。
最后强调一点,在类里面定义字段时,其实是可以赋初值的,但是使用带参数的构造方法之后,真正的值就是构造方法赋予的了,此时如果使用不带参数的默认构造方法,那么实例的各个字段的值就是我们定义字段时赋的值了,另外,就算我们没有给字段赋值,字段也会有默认的初值,比如String型的初值为null,int型的初值为0。
说了这么多,其实就是我对字段的一些小理解,说服力不一定够,但是看了下面的代码,一定就可以理解透了,复习的时候跟着敲一敲试一下效果是很不错的!下面是构造方法的代码示例:
package Liao;
class Mankind {
private String name = "Andy";
private int age = 18;
public Mankind() {
}
public Mankind(String name, int age) {
this.name = name;
this.age = age;
}
public Mankind(String name) {
this.name = name;
}
public Mankind(int age) {
this("Altman", age);
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
public class CStructTest1 {
public static void main(String[] args) {
Mankind man = new Mankind("Any", 24);
Mankind woman = new Mankind();
Mankind child = new Mankind("Ace");
Mankind elder = new Mankind(99);
System.out.printf("%s is %d years old now.", man.getName(), man.getAge());
System.out.println();
System.out.printf("%s is %d years old now.", woman.getName(), woman.getAge());
System.out.println();
System.out.printf("%s is %d years old now.", child.getName(), child.getAge());
System.out.println();
System.out.printf("%s is %d years old now.", elder.getName(), elder.getAge());
}
}
意思就是,如果有一些方法的功能很接近,比如都是输出或查找,那就可以将它们的名字设置为同一个,只要把参数的类型或数量改一改就好,这样就叫做方法重载,示例如下:
package Liao;
class Hello {
public void hello() {
System.out.println("Hello, world!");
}
public void hello(String name) {
System.out.println("Hello, " + name + "!");
}
public void hello(String name, int age) {
if (age < 18)
System.out.println("Hi, " + name + "!");
else
System.out.println("Hello, " + name + "!");
}
}
public class DOverloadTest1 {
public static void main(String[] args) {
Hello h = new Hello();
h.hello("Tom", 19);
}
}