黑马程序员--------构造方法

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

1.构造方法

1.构造:实例化一个对象;new Student();

2.构造方法:是在"实例化一个对象"时,由JVM自动调用的一个方法;

3.每个类,都必须至少有一个构造方法。我们可以不定义构造方法,编译器,会自动添加一个。

4.构造方法的格式:

                   1)."方法名":必须与"类名"一致,包括大小写;

                   2)."返回值类型":对于构造方法,不能定义"返回值类型",甚至是void。

                   3)."形参" : 可以有,可以没有。如果没有形参,小括号一定要写。

                   4)."修饰符":也可以有,后面会讲到,现在不需要加。

5.构造方法的特点:

                   1).它是在创建此类对象时,由JVM自动调用的一个方法;

                      当实例化之后,我们不能手动调用构造方法。

 

                   2).它不能有返回值;但可以写return;语句,表示结束方法的执行;

                   3).它一般是用来:初始化成员变量的。也可以做一些其它在实例化此类对象之前

                                   需要做的一些准备工作。

                   4).每个类都必须有一个构造方法,如果我们不定义,编译器会自动添加一个--无参的,任何事情都不做的。

                      如果我们定义了构造方法,那么系统就不会自动添加了。

                      class Student{

                               //如果我们不定义任何构造方法,编译器会隐式的添加一个如下的构造方法:无参,什么事情都不做

                               Student(){

                               }

                      }

 

1.1构造方法代码体现

 

/*

需求:为了描述事物更准确,发现事物对应的很多对象一创建时,

就有了,一些初始化的数据。在类中该如何完成的。

 

通过Java中的另一个小技术完成:就是构造函数。对象本身就是构造出来,

构造时,需要做一些动作这些应该定义在函数内。

 

构造函数(Constructor)有什么用?可以对对象创建进行初始化。

 

构造函数怎么在代码中体现呢?

1,没有返回值类型。因为构造对象,创建完就结束,需要结果。void也不要写,因为要有区别与一般函数。

2,构造函数名称和类名一致。

3,没有具体的返回值。

接下来,按照以上三点,在Person类中定义一个构造函数。

对象一创建就具备了姓名。

 

 

发现了问题?

没有学习构造函数时,对象也创建出来了。那么该对象是否有被构造呢?或者说是否有调用构造函数呢?

 

是的。必须调用!

那么类中那个构造函数是什么呢?

 

class Person
{
	//Person(){}//默认的空参数构造函数。
}

main()
{
	Person p = new Person();//这就已经调用了Person类中的空参数的构造函数。
							//类中有定义该构造函数吗?有的。只要定义一个类,
							//该类中默认就有一个空参数的构造函数,是编译器编译时添加到class文件中。
							//注意:如果在类中自定义了构造函数,那么默认的空参数构造函数编译器就不添加了。
							//原理:没有定义对象的初始化过程,编译器会添加一个默认的初始化过程。
							//      如果定义了指定的对象初始化过程,默认的就不添加了。
}

 

构造函数的细节:

1,一个类中可以有多个构造函数,它们的存在是以重载的形式体现的。

2,构造函数中也是有return语句的,用于结束初始化动作的。

3,构造函数是否能被private修饰呢?能,作用:其他程序无法创建该类的对象。

class Person
{
	private Person(){}
}
main()
{
	Person p = new Person();//创建对象无法初始化。
}

 

构造函数和一般函数的区别?

1,写法不一样。不重要。

2,运行上有差别,对象一创建就会调用对应的构造函数。

         一般方法是对象创建后,才会调用所需的一般函数。

问:有了构造函数初始化姓名,那么还需要setName方法吗?

需要,因为对象创建后,如果需要对数据进行修改,可以通过set完成。

3,构造函数在对象创建时,仅调用一次(初始化动作只做一次,而且先执行)。一般方法可以被对象调用多次。

class Person
{
	//Person(){}
	void Person(){}//这是一般函数。但不要这些书写,因为一般函数名称有规范。
}

main()
{
	Person p = new Person();
}


*/

class Person
{
	//属性:姓名,年龄。
	private String name;
	private int age;
	//一初始化,既没有姓名,又没有年龄。
	Person()
	{
		
	}
//	Person(int a)
//	{
//		if(a<0)
//			return;
//		age = a;
//	}


	//定义构造函数,对象一创建就具备姓名。
	Person(String n)
	{
		//将接收到的值赋值给对象的name
		name = n;
	}

	//一初始化既有姓名,又有年龄。
	Person(String n,int a)
	{
		name = n;
		age = a;
		
	}
	
	//行为。
	public void speak()
	{
		System.out.println("name="+name+",age="+age);
	}
}


class PersonDemo2 
{
	public static void main(String[] args) 
	{

		Person p1 = new Person();
		
//		Person p = new Person("lisi");//对象创建时,必须会调用对应的构造函数,因为对象需要初始化。
	
//		Person p2 = new Person("wangwu",23);
		
	}
}

1.2构造方法之间的调用引出的this

1.2.1this关键字:

 

         1.类中可以定义:成员属性、成员方法;

         2.当实例化一个类的对象时,在堆空间,会产生此类对象的空间,内部包含了所有"成员属性"。

           "成员方法"的字节码会被存储在"方法区";

         3.实例化多个对象,在堆中:每个对象都有独立的"成员属性"的空间,但"方法区中的方法的字节码"空间,

           只有一个;

         4.如果方法内部需要访问"成员变量",那么JVM就要区分是哪个对象调用的此方法,那么就会去访问哪个对象的

           成员属性。区分的方式:this

         5.每个类都有一个隐式的this变量;

           当实例化此类的一个对象时,由JVM自动为其赋值,赋值为:当前对象的引用;

         6.我们可以显示的使用this去访问"本类的--成员属性、成员方法";

         7.有两种情况,必须的显示的使用this关键字:

                   1).局部变量覆盖成员变量时;

                   2).在一个构造方法内调用另一个构造方法

1.2.2 this在代码中的体现
class Student{

	String name;
	int age;
	int num = 10;

	void show(){
		System.out.println(this.name + "," + this.age);//this可以调用本类的成员属性
	}
	void fun(){
		show();//OK的,可以这样直接调用
		this.show();//OK的,也可以这样调用;
	}
	void fun2(){
		int num = 20;//局部变量覆盖同名的成员变量,这个是可以的。
		System.out.println("num = " + num);//此时访问的num 就是局部的num
		System.out.println("this.num = " + this.num);//此时可以通过this关键字,显示的访问被覆盖的成员变量num
	}

}
class Demo 
{
	public static void main(String[] args) 
	{
		Student stu1 = new Student();
		stu1.name = "刘德华";
		stu1.age = 20;

		Student stu2 = new Student();
		stu2.name = "张学友";
		stu2.age = 22;

		Student stu3 = new Student();
		stu3.fun2();


	}
}

1.3super关键字

1.3.1特点

1).每个类都有的一个隐式的变量;

                   2).存储的是父类对象的引用;是实例化子类对象时,由JVM自动为其赋值的;

                   3).super可以访问父类的成员变量、成员方法、构造方法;

                   4).使用super()调用父类的构造方法的注意事项:

                                     A.super()调用父类构造方法的语句,只能出现在子类的某个构造方法内;

                                     B.使用super(实参)可以调用父类带参数的构造方法;

                                     C.super()调用父类的构造方法时,这条语句必须出现在子类构造方法的第一条有效语句;

                   5).什么时候必须使用super:

                                     A.子类成员覆盖了父类成员时,可以使用(super.父类成员)访问父类的被覆盖的成员;

                                     B.如果父类中没有无参构造方法,子类的每个构造方法都必须的使用super(实参)调用父类中带参的构造方法;

 

1.3.2 super代码应用
class Fu
{
	int num = 10;
	Fu(){
		System.out.println("Fu的构造方法");
	}
	Fu(int n){
		System.out.println("Fu的构造方法........."+n);
	}
	void show(){
		System.out.println("Fu的show()");
	}
}
class Zi extends Fu
{
	Zi(){
		
		super(22);//调用父类有参的构造方法
	
		System.out.println("Zi的构造方法");
		
	}
	Zi(String n){
		System.out.println("Zi的带参的构造方法");
	}

	void fun(){
		System.out.println("访问父类的成员变量:" + super.num);
		System.out.println("调用父类的成员方法:");
		
	}
}
class SuperDemo 
{
	public static void main(String[] args) 
	{
		Zi z = new Zi();

	}
}

1.4重载
构造方法的重载:

 

         1.构造方法是可以重载的:一个类中,可以定义多个构造方法。但形参列表不能完全相同;

         2.构造方法中"形参"的作用:一般是用来初始化"成员变量"。

         3.构造方法重载的意义:

                   1).方便程序员使用此类,在构造此类的对象时,非常的方便灵活。

                                     --如果构造时有数据时,可以调用"带参"的构造方法,可以直接为成员属性赋值;

                                       后期无需再调用set方法为成员属性赋值;

                                     --如果构造时没有数据,也可以调用"无参"的构造方法;后期再通过调用set方法

                                       为成员属性赋值;

         4.注意:当我们定义了某个构造方法后,编译器将不会为我们的类添加任何的构造方法;

 

class Student
{
	private String name;
	private int age;

	//可以编译通过,此方法,被当成是"普通成员方法"
	void Student(){
		System.out.println("我只是个普通成员方法");
	}
	//此方法,才是构造方法;
	Student(){
		System.out.println("Student类的无参构造方法......");
	}
	Student(String n){
		name = n;//作用:相当于setName()方法
		System.out.println("Student类的String的构造方法......");
	}
	Student(int n){
		age = n;//作用:相当于setAge()方法
		System.out.println("Student类的int的构造方法......");
	}
	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	//一些get和set方法;
	void setName(String name){
		this.name = name;

	}
	String getName(){
		return this.name;
	}
	void setAge(int age){
		this.age = age;
	}
	int getAge(){
		return this.age;
	}
}
class Demo 
{
	public static void main(String[] args) 
	{
		Student stu = new Student();//调用无参的构造方法
		stu.setName("张学友");
		stu.setAge(22);

		Student stu2 = new Student("张三");//调用String的构造方法
		Student stu3 = new Student(20);//调用int的构造方法

		Student stu4 = new Student("刘德华",20);
		System.out.println(stu4.getName() + "----" + stu4.getAge());
	}
}

 

1.5重写

         1.在子类中,可以定义跟父类相同的方法,这时,子类的方法覆盖父类中相同的方法,这叫:方法的重写

         2.重写的语法格式规则:

                            1.返回值类型 方法名     形参列表:必须全部一致;

                            2.子类的重写父类的方法时,"访问修饰符"可以跟父类相同,或者比父类更宽;宽--窄:public,protected,(默认),private

 

         3.如果返回值类型相同,但方法名和形参列表不同:编译通过。相当于方法重载。(但这不属于重载)

           如果返回值类型不同,方法名和形参列表相同:编译错误。按照重写的语法规则检查。

         4.父类中private的方法是不能被重写;
class Fu
{
	private void fun(){
		System.out.println("父类私有的fun()");
	}
	void show(){
	}
}
class Zi extends Fu
{
	void show(){
	}
	// 编译可以通过。但这绝不是重写;
	private void fun(){
		System.out.println("子类私有的fun()");
	}
}
class Demo 
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}

1.6 this和super以及重写和重载

 

方法重写和方法重载的区别?方法重载能改变返回值类型吗?

         1.重写:Override:要存在"子父类关系";子类定义了跟父类完全相同的方法:返回值类型 方法名形参列表完全相同,跟父类相同或更宽的访问修饰符;

           重载:Overload:只在"同一个类中",定义多个方法名相同,但形参列表不完全相同的方法。

         2.方法重载,跟返回值类型无关;

        

         this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

         1.this:

                   1).每个类都有的一个隐式的变量;

                   2).存储是当前对象的引用,是实例化此类的对象时,由JVM自动为其赋值的;

                   3).this可以访问本类的成员变量、成员方法、构造方法;

                   4).使用this()调用本类其它构造方法的注意事项:

                                     A.this()调用其它构造方法,这种语句只能出现在某个构造方法中;

                                     B.如果调用带参的构造方法,可以使用this(实参)方式调用;

                                     C.构造方法不能"递归调用";

                                     D.this()调用其它构造方法时,这种语句必须出现在这个构造方法的第一行有效语句;

                   5).什么时候必须使用this:

                                     A.局部变量覆盖成员变量;使用this访问被覆盖的成员变量;

                                     B.在本类的一个构造方法中调用本类的另一个构造方法时。this()或this(实参)

         2.super:

                   1).每个类都有的一个隐式的变量;

                   2).存储的是父类对象的引用;是实例化子类对象时,由JVM自动为其赋值的;

                  3).super可以访问父类的成员变量、成员方法、构造方法;

                   4).使用super()调用父类的构造方法的注意事项:

                                     A.super()调用父类构造方法的语句,只能出现在子类的某个构造方法内;

                                     B.使用super(实参)可以调用父类带参数的构造方法;

                                     C.super()调用父类的构造方法时,这条语句必须出现在子类构造方法的第一条有效语句;

                   5).什么时候必须使用super:

                                     A.子类成员覆盖了父类成员时,可以使用(super.父类成员)访问父类的被覆盖的成员;

                                      B.如果父类中没有无参构造方法,子类的每个构造方法都必须的使用super(实参)调用父类中带参的构造方法;

 

         注意:在一个构造方法中,不能同时使用this()和super()。因为它们都需要在第一行有效语句;

 

1.7子父类中构造函数的特点

1.7.1特点

当子父类都有构造函数时,发现结果为:

fu constructor run

zi constructor run

先执行了父类的构造函数,再执行子类的构造函数。

 

【这是为啥呢?】

因为子类的所有的构造函数中的第一行都有一句隐式语句 super(); //默认调用的是父类中的空参数的构造函数。

 

【子类中的构造函数为什么有一句隐式的super()呢?】

原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。

才可以更方便的使用父类中的内容。

 

【小结】

当父类中没有空参数构造函数时,子类的构造函数必须同构显示的super语句指定要访问的父类中的构造函数。

这就是传说中的子类实例化过程。

 

【实例化过程的细节】

1,如果子类的构造函数第一行写了this调用了本类其他构造函数,那么super调用父类的语句还有吗?

没有的,因为this()或者super(),只能定义在构造函数的第一行,因为初始化动作要先执行。

 

2,父类构造函数中是否有隐式的super呢?

也是有的。记住:只要是构造函数默认第一行都是super();

父类的父类是谁呢?super调用的到底是谁的构造函数呢?

Java体系在设计,定义了一个所有对象的父类Object ,

 

 

【总结】

类中的构造函数默认第一行都有隐式的super()语句,在访问父类中的构造函数。

所以父类的构造函数既可以给自己的对象初始化,也可以给自己的子类对象初始化。

 

如果默认的隐式super语句没有对应的构造函数,必须在构造函数中通过this或者super的形式明确调用的构造函数。

 

【问题】

1,this语句和super语句是否可以在同一个构造函数中出现呢?不行,因为必须定义在第一行。

2,为什么要定义在第一行呢?因为初始化动作要先执行。

1.7.2代码
class Fu extends Object
{
//	int count = 3;
	
	Fu()
	{
		//super();
		//显示初始化。
		System.out.println("fu constructor run..A..");
	}
	Fu(int x)
	{
		//显示初始化。
		System.out.println("fu constructor run..B.."+x);
	}
}
class Zi extends Fu
{
	Zi()
	{
		//super();
		System.out.println("zi constructor run..C..");
	}
	Zi(int x)
	{
		this();
		System.out.println("zi constructor run..D.."+x);
	}
}

class ExtendsDemo3 
{
	public static void main(String[] args) 
	{
//		new Zi();
		new Zi(6);

		new Student("lisi",21);
	}
}


//子类的实例化过程的应用。也是super调用的应用。
//什么时候用super调用父类中构造函数。只要使用父类的指定初始化动作,就在子类中通过super(参数列表)格式进行调用。

class Person
{
	private String name;
	private int age;
	public Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public void setName(String name)
	{
		this.name  = name;
	}
	public String getName()
	{
		return name;
	}
	public void setAge(int age)
	{
		this.age  = age;
	}
	public int getAge()
	{
		return age;
	}
}

class Student extends Person
{
	public Student(String name,int age)
	{

		//调用父类。使用父类的初始化动作。
		super(name,age);
	}
	public void study()
	{}
}

class Worker extends Person
{
	public Worker(String name,int age)
	{
		//调用父类。使用父类的初始化动作。
		super(name,age);
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员的Python学习视频中的构造方法是指在面向对象编程中用于初始化对象的特殊方法。在第十三章的视频中,具体介绍了构造方法的相关内容。构造方法通常被称为`__init__`方法,它会在创建对象时自动调用,并可以用来给对象的属性进行赋值。在构造方法中,可以使用参数来接收外部传入的值,并将其赋给对象的属性。构造方法的一些注意事项包括:构造方法必须以双下划线开头和结尾,构造方法可以有参数也可以没有参数,构造方法中可以进行属性的赋值操作等等。通过学习和应用构造方法,可以更好地理解和使用面向对象编程的概念和原理。如果想要安装Python的NumPy库,可以使用`pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy`命令来进行安装。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [三、python基础语法进阶篇(黑马程序猿-python学习记录)](https://blog.csdn.net/yinsefeixingchuan/article/details/128752143)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [8天Python从入门到精通 第十三章 面向对象 13.4 构造方法](https://blog.csdn.net/weixin_44226181/article/details/128911416)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值