前面的章节知识(点击跳转即可哦)
文章目录
8 类和对象 - 下
8.6 构造方法
构造方法:构造方法是类中非常特殊的一类方法,使用关键字new实例化对象时,实际上就调用的是该类的构造方法
构造方法的作用就是产生对象。
使用关键字new产生一个对象时,大致分为以下两步:
- 为对象在堆中分配空间,
- 调用对象的构造方法为成员变量进行赋值
(成员变量的默认值就是在构造方法在赋值的)
若成员变量初始化,程序在走到构造方法这步时,先赋值成员变量的默认值,再进行他们的初始化,然后进入构造方法内部。(可以具体在IDEA中具体调试跑一下)
构造方法的语法规则:
- 方法名称与类名称完全相同
- 构造方法没有返回值声明(也没有void)
- 一个类中至少存在一个构造方法,若没有显示定义,编译器会生成一个默认的无参构造
来看代码:
package ClassesAndObjects;
public class Test {
public static void main(String[] args) {
Card card = new Card();
}
}
class Card{
private int cardNum = 123456; //卡号
private double money = 214.4; //余额
private String passworfd = "123"; //密码
//构造方法
//方法名称要和类名称完全相同
//无返回值
public Card(){
System.out.println("构造方法");
}
}
输出结果:
构造方法
在主方法中只写了一行对象 的创建,就输出了 构造方法
的内容。说明使用关键字new产生一个对象时,构造方法就会执行。
当类中自定义了构造方法,则默认的无参构造就不再生成。
看代码:
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
Person per = new Person();
Person per1 = new Person("男");
}
}
class Person{
int a;
String name;
public Person(String sex){
name = "张三";
System.out.println(name + "的性别是" + sex);
}
}
程序在编译时,第五行就报错,执行后提示
自定义构造方法
后,此时默认的默认无参构造就没有了
8.6.1 构造方法重载
构造方法是为了类中的成员变量赋值的(成员变量的类型在类定义的时候就指定好了),此时的重载只可能是参数个数的不同(为不同的成员变量赋值)。个数不同并不是说只能一个参数个数为1的构造方法,而是在存在的几个成员变量中去挑选不同的一个
比如:
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
Person per1 = new Person("男");
Person per2 = new Person(18);
}
}
class Person{
String name = "张三";
int age;
String sex;
public Person(String sex){
this.sex = sex;
System.out.println(name + "的性别是" + sex);
}
public Person(int age) {
this.age = age;
System.out.println(name + "的年龄是"+ age);
}
}
输出结果:
张三的性别是男
张三的年龄是18
8.7 this 关键字
this
关键字:表示当前对象的引用
this
的作用:
-
调用当前对象的成员变量
-
调用当前对象的方法
——调用普通成员方法
——构造方法的互相调用
-
表示当前对象的引用
8.7.1 this-调用当前对象的成员变量
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
Person per2 = new Person(18);
System.out.println(per2.age);
}
}
class Person{
String name = "张三";
int age;
String sex;
public Person(int age) { //形参
age = age;
System.out.println(age + "有参构造");
}
}
输出结果是:
18有参构造
0
此时就会有一个问题,为什么构造方法中的age
是18,而成员变量age
是它的默认值0?
在程序的设计理念中(不止Java,还有C、C++、go、Python),就近匹配原则。编译器会找最近的相同名称的变量在哪。
public Person(int age) { //形参
age = age;
System.out.println(age + "有参构造");
}
在这段代码中,age = age
找到的变量并不是成员变量,而是构造方法传入的形参,和成员变量没有任何关系。
所以在输出结果时,构造方法内部的age是18.通过对象调用的成员变量age是0。
所以如何打破就近匹配原则,从类中找到成员变量呢?
那就是使用this
关键字,它的第一个作用:调用当前对象的成员变量。
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
Person per2 = new Person(18);
System.out.println(per2.age);
}
}
class Person{
String name = "张三";
int age;
String sex;
public Person(int age) {
this.age = age; //加上this,表示调用成员变量
System.out.println(age + "有参构造");
}
}
此时的输出结果:
18有参构造
18
8.7.2 this-调用类中的方法
调用类中的成员方法
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
Person per = new Person();
per.tests();
}
}
class Person{
String name = "张三";
int age;
String sex;
public void test(){
System.out.println("进入test方法");
}
public void tests(){
test(); // 不加this
this.test(); //加了this
System.out.println("进入tests方法");
}
}
输出结果:
进入test方法
进入test方法
进入tests方法
从代码中可以看出来,调用类中的成员方法,写不写this都一样,因为不写的话,编译器编译之后会默认加this
。
this 表示构造方法间的相互调用
public Person(String name) {
System.out.println("--------------");
this.name = name;
}
public Person(String name, int age) {
System.out.println("--------------");
this.name = name;
this.age = age;
}
public Person(String name, int age, String sex) {
System.out.println("--------------");
this.name = name;
this.age = age;
this.sex = sex;
}
代码中可以看到,不同参数的构造方法之间出现了重复的调用,那么这个时候就可以使用this(参数)
调用其他的构造方法。
-
this 调用其他的构造方法必须放在当前构造方法的首行。
-
this 调用构造方法不能成”环“。(就是这样规定的)
public Person(String name) {
System.out.println("--------------------");
this.name = name;
}
public Person(String name, int age) {
this(name);
this.age = age;
}
public Person(String name, int age, String sex) {
this(name,age);
this.sex = sex;
}
这两个代码的功能是相同的,但是在代码的简洁上却不同。
8.7.3 this-表示当前对象的引用
在这里 this 就像是一面镜子,this在哪个对象里,this就代表这个对象。
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
Person per = new Person();
System.out.println(per); //打印的是引用类型的地址
per.who(); //打印this
System.out.println();
Person per1 = new Person();
System.out.println(per1);
per1.who();
}
}
class Person{
String name = "张三";
int age;
String sex;
public void who(){
System.out.println(this);
}
}
输出结果:
ClassesAndObjects.Person@1540e19d
ClassesAndObjects.Person@1540e19d
ClassesAndObjects.Person@677327b6
ClassesAndObjects.Person@677327b6
8.8 代码块
代码块指的是使用 {}括起来的一段代码,称为代码块。
根据定义的代码块的位置以及关键字的不同分为一下四种代码块:
- 普通代码块,定义在方法中,使用{}括起来的代码块
- 成员代码块,定义在类中,使用{}括起来的代码块,也叫构造块
- 静态代码块
- 同步代码块,在多线程中会提到
成员代码块(构造块)
构造块:直接定义在类中,不加任何修饰符的代码块,优先于构造方法执行,有几个对象产生,就调用几次构造块。
静态代码块
定义在类中,使用static 修饰的代码块,在类加载的时候执行一次,与对象无关,无论产生多少对象,静态代码块只在类加载的时候执行一次。
package ClassesAndObjects;
public class Test4_15 {
static {
System.out.println("进入主类的静态代码块");
}
public static void main(String[] args) {
System.out.println("进入主方法");
}
}
输出结果:
进入主类的静态代码块
进入主方法
这段代码说明:静态代码块在加载主类的时候执行,优先于主方法(静态方法)。
JVM要执行主方法,首先要加载主类,主类加载时静态块就执行了
注意:
类中的静态变量表示类的属性,存在于方法区中,类定义的时候类的属性就已经有了,放在了方法区。这个时候,类只是定义了,还没有进行加载。
8.9 toString 方法
匿名对象: new 出来的对象,没有引用指向,使用一次后就销毁
new Person(); (Person() 表示一个类)
匿名对象常用于测试类中的某些功能,使用一次后就销毁
toString 方法, 一定要注意大小写。
当一个引用类型的变量调用println函数打印时,默认输出的都是引用类型的地址,(不是真正的内存地址,Java中程序员是无法知道任何确切
的内存地址。)
package ClassesAndObjects;
public class Test4_15 {
public static void main(String[] args) {
System.out.println(new Person());
}
}
class Person{
String name;
int age;
String sex;
public Person(){
System.out.println("无参构造");
}
}
输出结果:
无参构造
ClassesAndObjects.Person@1540e19d
我们调用打印函数打印一个引用的时候,大概率是打印这个对象具体的属性值内容。就是实现toString();
快捷键:右键点击Generate
(按下Alt+insert) -> 点击toString()
即可,设置toString()方法。
要是对大家有所帮助的话,请帮我点个赞吧。