构造器
构造器的作用就是保证初始化,java中的”创建“和”初始化“绑定在一起,两者不能分离。
由于构造方法(构造器)是如此特殊,所以构造方法的名称就是类名。构造方法的参数没有限制,在方法内部,也可以编写任意语句。但是,和普通方法相比,构造方法没有返回值(也没有void),调用构造方法,必须用new操作符。
没有在构造方法中初始化字段时,引用类型的字段默认是null,数值类型的字段用默认值,int类型默认值是0,布尔类型默认值是false
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this.name = name;
this.age = 12;
}
public Person() {
}
}
如果调用new Person(“Xiao Ming”, 20);,会自动匹配到构造方法public Person(String, int)。
如果调用new Person(“Xiao Ming”);,会自动匹配到构造方法public Person(String)。
如果调用new Person();,会自动匹配到构造方法public Person()。
this关键字
this关键字只能在方法内部使用,表示对”调用方法的那个对象”的引用.
一个构造方法可以调用其他构造方法,这样做的目的是便于代码复用。调用其他构造方法的语法是this(…):
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name) {
this(name, 18); // 调用另一个构造方法Person(String, int)
}
public Person() {
this("Unnamed"); // 调用另一个构造方法Person(String)
}
}
public class Leaf{
int i=0;
Leaf increment(){
i++;
return this; //this关键字当前Leaf类型对象
//返回了对当前对象的引用
}
void print(){
System.out.println("i =" + i);
}
public static void main(String[] args){
Leaf x = new Leaf();
x.increment().increment().increment().print();
}
}/*Output:
i=3;
*//
方法重载
为了让方法名相同而参数列表不同的构造器同时存在就要用到方法重载。
这种方法名相同,但各自的参数不同,称为方法重载(Overload)。
注意:方法重载的返回值类型通常都是相同的。
方法重载的目的是,功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。
基本类型的重载
常数值5被当作int型参数.如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际参数类型就会被提升.(向上转型自动发生)
char型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int型.
方法接受较小的基本类型作为参数.如果传入的实际参数较大,就得通过类型转换执行窄化转换(强制向下转型),不这么做,编译器会报错.
char < byte < short <int <long <flaot < double
默认构造器
类中没有构造器.则编译器会自动创建一个默认构造器.
如果自己定义了一个构造器(无论是否有参数),编译器就不会帮你自动出创建默认构造器.因为编译器会认为是刻意省略了默认构造器.
static
在static方法的内部不能调用非静态方法,反过来可以.
实例字段在每个实例中都有自己的一个独立“空间”,但是静态字段只有一个共享“空间”,所有实例都会共享该字段。举个例子
class Person {
public String name;
public int age;
// 定义静态字段number:
public static int number;
}
对于静态字段,无论修改哪个实例的静态字段,效果都是一样的:所有实例的静态字段都被修改了,原因是静态字段并不属于实例
public class Main {
public static void main(String[] args) {
Person ming = new Person("Xiao Ming", 12);
Person hong = new Person("Xiao Hong", 15);
ming.number = 88;
System.out.println(hong.number); //88
hong.number = 99;
System.out.println(ming.number); //99
}
}
class Person {
public String name;
public int age;
public static int number;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
输出:
88
99
静态方法
有静态字段,就有静态方法。用static修饰的方法称为静态方法。
调用实例方法必须通过一个实例变量,而调用静态方法则不需要实例变量,通过类名就可以调用。静态方法类似其它编程语言的函数。例如:
public class Main {
public static void main(String[] args) {
Person.setNumber(99);
System.out.println(Person.number);
}
}
class Person {
public static int number;
public static void setNumber(int value) {
number = value;
}
}
数组初始化
定义一个数组类型,在对数组元素赋值的时候,里面的元素进行初始化,实际还是原对象的初始化
class Phone{
Phone(int i){
System.out.println("Phone"+i);
}
}
class Person{
private Phone phone = new Phone(1);
Person(){
System.out.println("person");
}
}
public class MM {
public static void main(String[] args) {
Person[] persons = new Person[3]; //此时只是一个空的容器(引用数组),初始化并未进行
persons[0] = new Person(); //只有当将对象new出来放入数组时,初始化进行
}
}
数组初始化三种方式:
1.int[] a={1,2,3,4,5}
2.int[] a;
a=new int[5];
3.int[] a = new int[5];
所有数组(无论它们的元素是对象还是基本类型)都有一个固有成员length,可以通过它获知数组内包含了多少个元素,但不能对其修改.
String字符串都有一个固有方法length()
可变参数列表
可变参数列表等同于数组类型 且会发生向上转型问题,注意方法的歧义性.
默认行为(如果没有定义toString()方法),打印类的名字和对象的地址.
public class OptionalTrailingArguments {
static void f(int required ,String... trailing){
System.out.print("required :" + required +" ");
for (String s:trailing) {
System.out.print(s+" ");
}
System.out.println();
}
public static void main(String[] args) {
f(1,"one");
f(2,"two","three");
f(0);
}
}Output:
required :1 one
required :2 two three
required :0
枚举类型
枚举类在整个JVM中: 只加载一次 调用时加载
编译器会为枚举类创建toString()方法,只是打印enum实例的名字
编译器还会创建ordinal()方法,用来表示某个常量的声明顺序
public enum Spiciness{
NOT,MILD,MEDIUM,HOT,FLAMING_F
}
枚举类型的实例是常量,命名都用大写字母表示(如果在一个名字中有多个单词,用下划线将它们隔开)