class People {
public String name;
public int age;
public void eat() {
System.out.println(name + "吃饭");
}
public void swim() {
System.out.println(age + "岁的" + name + "游泳");
}
}
public class Test {
//练习书写Java的类
public static void main(String[] args) {
People people = new People();
people.name = "小王";
people.age = 22;
people.eat();
people.swim();
}
}
运行结果:
②定义洗衣机类
class WashMachine {
public String name;
public String color;
public int power;
public void wash(){
System.out.println(name + "在工作洗衣服");
}
}
public static void main(String[] args) {
WashMachine w = new WashMachine();
w.name = "haie";
w.color = "wite";
w.power = 1000;
w.wash();
}
运行结果:
public static void main(String[] args) {
People people = new People();
people.name = "小王";
people.age = 22;
people.eat();
people.swim();
}
通过new关键字从People类中实例化出一个people对象。类等代码都在方法区。
实例化数组对象:
public static void main(String[] args) {
People[] p = new People[2]; //创建数组
for (int i = 0; i < p.length; i++) {
p[i] = new People(); //实例化对象
}
p[0].name = "小王";
p[0].age = 22;
p[1].name = "小帅";
p[1].age = 21;
p[0].eat();
p[1].eat();
}
运行结果:
注意:
People[] p = new People[2];
p[i] = new People();
第一条语句是创建数组,下面一条语句是实例化对象。
成员变量和局部变量
成员变量:在类里面,方法的外面
局部变量:在方法的里面
成员变量随着对象的创建而产生,对象的销毁而结束(生命周期)
局部变量进入方法创建,出方法结束(生命周期)
成员变量可以不用赋初始值,局部变量在定义的时候必须赋初始值。
引入this——为什么要有this引用
使用setDate方法给对象赋初始值,并且形参和成员变量不重名
class Person {
public String name;
public int age;
public void setDate(String n, int a) {
name = n;
age = a;
}
public void eat() {
System.out.println(name + "吃饭");
}
public void show() {
System.out.println("年龄:" + age + " 姓名:" + name);
}
}
public class Test {
//this引用
public static void main(String[] args) {
Person person = new Person();
person.setDate("小王",22);
person.show();
}
}
运行结果:
分析:可以正常赋值
加入使用setDate方法给对象赋初始值,并且形参和成员变量重名
则:
public void setDate(String name, int age) {
name = name;
age = age;
}
运行结果:
分析:没能成功赋值,并且在 public void setDate(String name, int age) { name = name; age = age; }
中出现的name和age都是形参局部变量的,因为局部变量优先原则,所以对象的成员变量的值还是创建对象的时候的初始值,int的初始值是0,String的初始值是null。为了避免这种情况的出现——引出this。
this的三种用法:(以下将围绕这3个方面总结)
①this访问成员变量 this.name
②this访问成员方法 this.func
③this访问构造方法 this(…)
public void setDate(String name, int age) {
this.name = name;
this.age = age;
}
再次运行程序,程序的运行结果:
分析:赋值成功
每个成员方法的第一个参数默认是this(隐式参数),this是“成员方法”第一个隐藏的参数。
成员变量赋值前加上this指明是给当前对象的name和age赋值,谁调用这个方法,它传过去的时候this就代表谁。
this引用指向当前对象,在成员方法中所有成员变量的操作都是通过该引用去访问的,this引用的是调用成员方法的对象,this代表当前对象的引用。
this的类型与当前对象的类型是一致的,即对应类类型引用,哪个对象调用就是哪个对象的引用类型。
person引用的地址
this引用的地址(与person相同)
this只能引用当前对象,不能再引用其他对象。
在上述中,每次给对象初始化都要调用setDate方法,比较麻烦,那么能不能在构造对象(实例化对象)的时候就初始化?——可以!构造方法!
什么是构造方法:构造方法是一个特殊的成员方法,①这个方法没有返回值(没有void);②方法名和类名一样。③在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次(相当于人的出生,每个人只出生一次)。④构造方法可以方法重载(根据自己的需求提供不同参数的构造方法)。
无参数构造方法
class Person {
public String name;
public int age;
public Person() {
System.out.println("没有参数的构造方法被被调用了");
}
public void setDate(Person this,String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "吃饭");
}
public void show() {
System.out.println("年龄:" + age + " 姓名:" + name);
}
}
public class Test {
//this引用
public static void main(String[] args) {
Person person = new Person();
person.show();
}
}
运行结果:
class Person {
public String name;
public int age;
public Person() {
System.out.println("没有参数的构造方法被被调用了");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参数的构造方法被调用");
}
public void setDate(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "吃饭");
}
public void show() {
System.out.println("年龄:" + age + " 姓名:" + name);
}
}
public class Test {
//this引用
public static void main(String[] args) {
Person person = new Person("小王",21);
person.show();
}
}
运行结果:
Person person = new Person("小王",21);
在实例化对象的时候,就直接给构造方法传参了
// public Person() {
// System.out.println("没有参数的构造方法被被调用了");
// }
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参数的构造方法被调用");
}
Person person = new Person();
// Person person = new Person("小王",21);
在new对象的时候不给他传参数,Person person = new Person();
,说明调用的是不带参数的构造方法,但是此时因为用户写了有参构造方法,Java不再提供默认的无参构造方法。
提示报错信息:
总结:
①如果没有写任何的构造方法,此时Java会帮我们提供一个默认的不带参数的构造方法
②如果自己写了构造方法,不管写了什么样的构造方法,Java都不会提供哪个默认的不带参数的构造方法了。
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间,开辟空间是实例化的时候干的事。
构造方法的特性:
①名字与类名相同
②没有返回值类型,设置成void也不行
③创建对象的时候由编译器自动调用,在对象的生命周期中只调用一次
④构造方法可以重载
⑤对对象的成员初始化,不负责给对象开辟空间
this访问成员方法
public void eat() {
System.out.println(name + "吃饭");
}
public void show() {
this.eat();
System.out.println("年龄:" + age + " 姓名:" + name);
}
运行结果:
分析:可以看到eat方法也被执行了,注意this只能在成员方法中使用,在main/静态方法中不能用this
如图所示,在main方法/静态方法中使用this出现报错提示。
public Person() {
this("小王",22);
// System.out.println("没有参数的构造方法被被调用了");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
// System.out.println("有参数的构造方法被调用");
}
Person person = new Person();
运行结果:
this调用当前对象的其他构造犯法,this(…)必须是构造方法中的第一条语句,必须放到第一行(否则会报错),并且只能在构造方法内部才能使用this(…)
this(,)不能形成循环:不能有参构造方法通过this调用无参构造方法的同时,无参构造方法又通过this调用有参构造方法。
成员变量会默认初始化,局部变量在使用时必须要初始化,但是成员变量不用。
当调用完成构造方法,那么对象就生成了。
主要有以下两个过程:
①为对象分配内存:说明在调用构造方法之前,内存已经分配好了,那么当前对象的引用一定是有的,所有此时可以拿到对象的引用,因此在接下来的构造方法中可以用到this
②调用合适的构造方法:在调用构造方法之前还有一个初始化,初始化锁分配的空间,即对象空间被申请好之后,对象中包含的成员已经设置好了初始值。调用构造方法是为了给对象中各个成员赋值,使其值更具有意义。
当一个引用赋值为null的时候,代表这个引用不指向任何对象
Person person = null;
person.show();
则会出现空指针异常报错,因为值为null不指向任何对象,不能调用show成员方法。
Person person1 = new Person();
Person person2 = new Person();
person1 = person2;
person1 = person2;
这个代表person1这个引用指向了person2这个引用指向的对象,而不是person1的引用指向了person2引用,引用不能指向引用,引用一定是指向对象的。
Person person1 = new Person();
person1 = new Person();
person1 = new Person();
person1 = new Person();
分析:
第一条语句:person1指向的地址
第二条语句:person1指向的地址
最后一条语句:person1指向的地址
最后person1只是指向了1个对象(最后那条语句),中途创建的对象都被回收了。