13-方法及构造

方法是java语言中非常基本的一个组成。
一个class可以包含多个field但是,直接把field用public暴露给外部可能会破坏封装性,使用private修饰field,可以拒绝外部访问。
class Person { private String name; private int age; } 把field从public改成private,外部代码不能访问这些field,需要使用方法(method)来让外部代码可以间接修改field。 public class Main { public static void main(String[] args) { Person ming = new Person(); ming.setName("Xiao Ming"); // 设置name ming.setAge(12); // 设置age System.out.println(ming.getName() + ", " + ming.getAge()); } } class Person { private String name; private int age; public String getName() { return this.name; }//this表示实例本身 public void setName(String name) { this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { if (age < 0 || age > 100) { throw new IllegalArgumentException("invalid age value"); }//超出范围抛出异常 this.age = age; } } 虽然外部代码不能直接修改private字段,但是,外部代码可以调用类中定义的方法setName()和setAge()来间接修改private字段。在方法内部,我们就有机会检查参数对不对。所以,一个类通过定义方法,就可以给外部代码暴露一些操作的接口,同时,内部自己保证逻辑一致性。 定义方法 外部代码通过public方法操作实例,内部代码可以调用private方法。 修饰符 方法返回类型 方法名(方法参数列表) { 若干方法语句; return 方法返回值; } //返回类型void 无需return private方法 相比于public方法,private方法和private字段一样,不允许外部调用,定义private方法的理由是内部方法是可以调用private方法的。例如: public class Main { public static void main(String[] args) { Person ming = new Person(); ming.setBirth(2008); System.out.println(ming.getAge()); } } class Person { private String name; private int birth; public void setBirth(int birth) { this.birth = birth; } public int getAge() { return calcAge(2019); // 调用private方法 } // private方法: private int calcAge(int currentYear) { return currentYear - this.birth; } } 这个Person类没有定义age字段,获取age时,通过方法getAge()返回的是一个实时计算的值,并非存储在某个字段的值。这说明方法可以封装一个类的对外接口,调用方不需要知道也不关心Person实例在内部到底有没有age字段。 this变量 在方法内部,可以使用一个隐含的变量this,它始终指向当前实例。如果没有命名冲突,可以省略this,但是,如果有局部变量和字段重名,那么局部变量优先级更高,就必须加上this: class Person { private String name; public void setName(String name) {//局部变量 name this.name = name; // 前面的this不可少,少了就变成局部变量name了 } } 可变参数 可变参数用 类型... 定义,可变参数相当于数组类型: class Group { private String[] names; //可变字符型 public void setNames(String... names) { this.names = names; } } //调用 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 也可以将可变参数改写为String[]类型,但调用方需要自己先构造String[],而且调用方可以传入null, 而可变参数可以保证无法传入null,因为传入0个参数时,接收到的实际值是一个空数组而不是null。 Group g = new Group(); g.setNames(new String[] {"Xiao Ming", "Xiao Hong", "Xiao Jun"}); // 传入1个String[] Group g = new Group(); g.setNames(null); //传入null 参数绑定 基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响。 public class Main { public static void main(String[] args) { Person p = new Person(); int n = 15; // n的值为15 p.setAge(n); // 传入n的值 System.out.println(p.getAge()); // 15 n = 20; // n的值改为20 System.out.println(p.getAge()); // 15 } } class Person { private int age; public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } } 引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方。 public class Main { public static void main(String[] args) { Person p = new Person(); String bob = "Bob"; p.setName(bob); // 传入bob变量 System.out.println(p.getName()); // "Bob" bob = "Alice"; // 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; } } 构造方法 构造方法就是在创建实例的同时初始化实例中的字段。 public class Main { public static void main(String[] args) { Person p = new Person("Xiao Ming", 15); System.out.println(p.getName()); System.out.println(p.getAge()); } } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; }//构造方法 public String getName() { return this.name; } public int getAge() { return this.age; } } 构造方法的名称就是类名,构造方法的参数没有限制,在方法内部,也可以编写任意语句。但是,和普通方法相比,构造方法没有返回值(也没有void),调用构造方法,必须用new操作符。如果一个类没有定义构造方法,编译器会自动生成一个默认构造方法,它没有参数,也没有执行语句,默认构造方法,初始化实例的时候:引用类型的字段默认是null,数值类型的字段用默认值,int类型默认值是0,布尔类型默认值是false。手动编写构造方法后,就不会在自动生成默认构造。 class Person { public Person() { } }//编译器自动生成的默认构造方法 多构造方法 可以定义多个构造方法,在通过new操作符调用的时候,编译器通过构造方法的参数数量、位置和类型自动区分。 class Person { private String name; private int age; public Person(String name, int age) {//方法1 this.name = name; this.age = age; } public Person(String name) {//方法2 this.name = name; this.age = 12; } public Person() {//方法3 } } /* 如果调用new Person("Xiao Ming", 20);,会自动匹配到构造方法1 如果调用new Person("Xiao Ming");,会自动匹配到构造方法2 如果调用new Person();,会自动匹配到构造方法3 */ 一个构造方法可以调用其他构造方法,这样做的目的是便于代码复用。调用其他构造方法的语法是this(…) class Person { private String name; private int age; public Person(String name, int age) {//方法1 this.name = name; this.age = age; } public Person(String name) {//方法2 this(name, 18); // 调用方法1 } public Person() {//方法3 this("Unnamed"); // 调用方法2 } } 方法重载 在一个类中,我们可以定义多个方法。如果有一系列方法,它们的功能都是类似的,只有参数有所不同,那么,可以把这一组方法名做成同名方法,也称为方法重载(Overload)。 注意:方法重载的返回值类型通常都是相同的。 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 + "!"); } } } String类提供了多个重载方法indexOf(),可以查找子串: int indexOf(int ch):根据字符的Unicode码查找; int indexOf(String str):根据字符串查找; int indexOf(int ch, int fromIndex):根据字符查找,但指定起始位置; int indexOf(String str, int fromIndex)根据字符串查找,但指定起始位置。

猜你喜欢

转载自www.cnblogs.com/nsss/p/11417480.html