方法
包括:创建实例、定义方法、方法参数、参数绑定、构造方法、方法重载
输出结果都写在了注释中
创建实例
public class demo11{
// 创建实例(instance)
public static void main(String[] args){
// 定义了class,只是定义了对象模版,而要根据对象模版创建出真正的对象实例,必须用new操作符
// Person ming是定义Person类型的变量ming,而new Person()是创建Person实例
Person ming = new Person();
ming.name = "Xiao ming";
ming.age = 18;
}
}
class Person {
// class表示一个类
// 一个class可以包含多个字段(field),字段用来描述一个类的特征
// public是用来修饰字段的,它表示这个字段可以被外部访问
public String name;
public int age;
}
定义方法(get,set)
public class demo12 {
// 方法
public static void main(String[] args){
Person ming = new Person();
ming.setName("Xiao ming");
ming.setAge(18);
System.out.println(ming.getName() + "," + ming.getAge());
// Xiao ming,18
}
}
class Person{
// 外部代码不能直接读取private字段
// 但可以通过getName()和getAge()间接获取private字段的值
// 并且内部方法是可以调用private方法的
public String name;
public int age;
public String getName() {
return name; // 相当于this.name
}
public void setName(String name) {
if(name == null||name.isBlank()){
throw new IllegalArgumentException("invalid name");
}
// 在方法内部,可以使用隐含的变量this,它始终指向当前实例
// 通过this.{field}可以访问当前实例的字段
// 如果没有命名冲突,可以省略this
// 如果有局部变量和字段重名,那么局部变量优先级更高,就必须加上this
this.name = name.strip(); // .strip()去掉收尾空格
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age < 0||age > 100){
throw new IllegalArgumentException("invalid age value");
}
this.age = age;
}
}
方法参数
public class demo13 {
public static void main(String[] args){
Person ming = new Person();
// 调用setNameAndAge()方法时,必须有两个参数,且第一个参数必须为String,第二个参数必须为int
ming.setNameAndAge("Xiao mung", 18);
Group g = new Group();
g.setNames("Xiao Ming", "Xiao Hong", "Xiao Jun"); // 传入3个String
g.setNames("Xiao Ming", "Xiao Hong"); // 传入2个String
g.setNames("Xiao Ming"); // 传入1个String
g.setNames(); // 传入0个String
}
}
class Person{
private String name;
private int age;
//传入两个参数
public void setNameAndAge(String name,int age){
this.name = name;
this.age = age;
}
}
class Group {
private String[] names;
//可变参数
public void setNames(String... names) {
this.names = names;
}
}
参数绑定
public class demo14 {
// 参数绑定
public static void main(String[] args){
Person p = new Person();
//基本类型参数传递
int n = 18;
p.setAge(n);
System.out.println(p.getAge());
// 18
n = 20;
System.out.println(p.getAge());
// 18
// 从结果可知,修改外部的局部变量n,不影响实例p的age字段
// 原因是setAge()方法获得的参数,复制了n的值,因此,p.age和局部变量n互不影响
Person p1 = new Person();
// 引用参数传递
String[] fullname = new String[]{"Allen","Smith"};
p1.setName(fullname);
System.out.println(p1.getName());
// Allen Smith
fullname[0] = "Jhon";
System.out.println(p1.getName());
// Jhon Smith
// 调用方的变量,和接收方的参数变量,指向的是同一个对象
// 双方任意一方对这个对象的修改,都会影响对方
}
}
class Person{
private int age;
private String[] name;
public String getName() {
return this.name[0] + " " + this.name[1];
}
public void setName(String[] name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class demo15 {
// String类型参数绑定
public static void main(String[] args) {
Person p = new Person();
String bob = "Bob";
p.setName(bob);
System.out.println(p.getName());
// Bob
bob = "Alice";
System.out.println(p.getName());
// Bob
}
}
class Person {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
关于引用类型参数传递的详细解释
首先,在Java中,所有参数传递都是:
值传递(pass by value)
基本数据类型(int
, double
, boolean
等):传递的是 数值的副本。
引用数据类型(数组、对象等):传递的是 引用的副本(即对象地址的拷贝,不是对象本身)。
String[] fullname = new String[]{"Allen", "Smith"};
p1.setName(fullname);
这里传的是一个数组引用的副本。
p1.name
和 fullname
都指向了 同一个数组对象。
[fullname] ----> ["Allen", "Smith"]
↑
[p1.name] ------------┘
fullname[0] = "Jhon";
这里修改的是数组内部的内容,因此 p1.getName()
的输出也变化了,变成了 "Jhon Smith"
。
[fullname] ----> ["Jhon", "Smith"]
↑
[p1.name] -----------┘
总结: 修改数组的元素,相当于修改了同一个内存里的对象。引用本身是复制的,但引用指向的对象是同一个。
String bob = "Bob";
p.setName(bob);
这里bob
是一个String
对象。
p.setName(bob)
,把bob这个引用的副本传入了setName
方法,然后把它赋值给了this.name
。
[bob] ----> "Bob"
↑
[p.name] ---------┘
bob = "Alice";
这里不是修改原来的 "Bob"
对象。
Java中的String
是不可变对象(immutable) ,一旦创建,就不能修改。
bob = "Alice";
这行代码实际上是让bob
这个变量指向了一个新的"Alice"
字符串对象,而不是改变原来的 "Bob"
对象。
[bob] ----> "Alice"
[p.name] ----> "Bob"
总结:String
是不可变对象,bob = "Alice"
是新建对象,跟之前传入p.setName(bob)
没有任何联系。指针断了,所以p.getName()
还是输出"Bob"
。
传递内容 | 结果 |
---|---|
基本类型 | 复制值,互不影响 |
引用类型(数组、对象等) | 复制引用,指向同一对象,修改对象内容会相互影响 |
特殊的 String | 虽然是引用,但不可变,改变变量实际上是指向新的对象,互不影响 |
构造方法
默认构造方法(无参构造方法)
如果你不写任何构造方法,Java 会给你一个隐式的无参构造器:
public class Animal {
// Java会自动添加一个public Animal() {}
}
Animal a = new Animal(); // 调用默认构造器
有参构造方法
public class demo16 {
// 构造方法
// 是 Java 类中的一种特殊方法,用来创建对象并进行初始化
public static void main(String[] args) {
Person p = new Person("Xiao Ming", 15);
// 如果我们自定义了一个构造方法,那么,编译器就不再自动创建默认构造方法
// Person p = new Person(); 编译错误:找不到这个构造方法
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
class Person {
private String name; // 默认初始化为null
private int age; // 默认初始化为0
// 构造方法的名字必须和类名相同,且没有返回类型(连void也没有)
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
方法重载
public class demo17 {
//构造方法的重载
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person("Xiaoming",12);
Person p3 = new Person("Xiaohong");
System.out.println(p1.getAge() +" " + p1.getName());
System.out.println(p2.getAge() +" " + p2.getName());
System.out.println(p3.getAge() +" " + p3.getName());
// 0 Unamed
// 15 Xiaoming
// 12 Xiaohong
}
}
// 构造方法可以重载,同一个类里可以写多个构造方法,只要参数不同
class Person {
// 可以对字段直接进行初始化
private String name = "Unamed";
private int age = 0;
// 无参构造法
public Person() {
}
// 有参构造法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 不同参数的有参构造法
public Person(String name) {
this.name = name;
this.age = 12;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
此外,String
类提供了多个重载方法indexOf()
,可以查找子串的索引:
int indexOf(int ch)
:根据字符的Unicode码查找;
int indexOf(String str)
:根据字符串查找;
int indexOf(int ch, int fromIndex)
:根据字符查找,但指定起始位置;
int indexOf(String str, int fromIndex)
根据字符串查找,但指定起始位置。
public class demo18 {
public static void main(String[] args){
String s = "Hello JavaWorld!";
int n1 = s.indexOf('a');
int n2 = s.indexOf("llo");
int n3 = s.indexOf('o',5);
System.out.println(n1 + "n" + n2 + "n" + n3);
// 7
// 2
// 11
}
}
Comments NOTHING