Java入门——构造方法详解

关于Java类中的构造方法:

  • 构造方法又称为构造函数/构造器/Constructor

  • 构造方法语法结构:
    [修饰符列表] 构造方法名 (形参列表){
    构造方法体;
    }

  • 普通方法语法结构:
    [修饰符列表] 返回值类型 方法名(形参列表){
    方法体;
    }

  • 对于构造方法来说,“返回值类型”,不需要指定,并且也不能写void,如果写上void,这个方法就变成了普通方法

  • 对于构造方法来说,构造方法的方法名必须和类名保持一致

  • 构造方法的作用?
    构造方法存在的意义,是通过构造方法的调用,可以创建对象

  • 构造方法应该怎么调用?

    普通方法调用:
    类名.方法名(实参列表)修饰符列表有static关键字的
    引用.方法名(实参列表)修饰符列表没有static关键字的

    构造方法的调用:
    new 构造方法名(实参列表)

  • 构造方法在调用后有返回值吗?
    每一个构造方法在执行结束后都有返回值,但是这个“return 值;”语句不需要写,构造方法结束的时候java程序自动返回值。并且返回值类型是构造方法所在类的类型,由于构造方法的返回值类型是类本身,所以返回值类型不需要写

  • 当一个类中没有定义任何构造方法的时候,系统会默认给该类构造一个无参数的构造方法,这个构造方法被称为“缺省构造器”

  • 当一个类显示的将构造方法定义出来了,那么系统将不再会给这个类提供缺省构造器,建议在实际开发中,手动为当前类提供无参数的构造方法,因为无参数构造方法太常用了。

  • 构造方法支持重载机制,在一个类当中编写多个构造方法,这多个构造方法显然构成方法重载

public class ConstructorTest01 {

	public static void main(String[] args) {

		//创建一个User对象
		//调用User类的构造方法来完成对象的创建
		//记住只要是标识符后面带括号的,就一定是方法,这里new后面的User不是类名而是构造方法名!!
		//而等号左边的User 是一个引用数据类型,指的是通过new来调用User()构造方法,通过User类型的u1变量来存储这个对象的内存地址
		//以下程序创建了4个对象,只要构造函数调用就会创建对象,并且一定是在“堆内存”当中开辟空间
		User u1=new User();
		User u2=new User(10);
		User u3=new User("zhangsan");
		User u4=new User(10,"zhangsan");
		
		//调用带有static的方法
		ConstructorTest01.doSome();
		doSome();
		
		//调用不带static的方法
		//doOther方法存在于ConstructorTest01类中,所以需要创建ConstructorTest01对象
		//创建ConstructorTest01对象,调用无参数构造方法
		ConstructorTest01 t=new ConstructorTest01();//没有任何构造方法会默认有缺省构造器
		t.doOther();
		
	}
	
	public static void doSome() {
		System.out.println("do some!");
	}
	
	public void doOther() {
		System.out.println("do other!");
	}
	
}
public class User {

	//无参数的构造方法
	public User() {
		System.out.println("User's Default Construction Invoke!");
	}

    //有参数的构造方法
	public User(int i) {
		System.out.println("带有int类型参数的构造器");
	}
	
	//有参数的构造方法
	public User(String name) {
		System.out.println("带有String类型参数的构造器");
	}
	
	//有参数的构造方法
	public User(int i,String name) {
		System.out.println("带有int,String类型参数的构造器");
	}
	

}

构造方法的作用:

  • 创建对象
  • 给实例变量赋值
    成员变量之实例变量,属于对象级别的变量,这种变量必须现有对象才能实例变量。
    实例变量没有手动赋值的时候,系统默认赋值,那么这个系统默认赋值是在什么时候完成的呢?

是在类加载的时候吗?
不是,因为类加载的时候只加载了代码片段,还没来得及创建对象,所以此时实例变量并没有初始化

实际上,实例变量的内存空间是在构造方法执行过程当中完成开辟的。完成初始化的。系统在默认赋值的时候,也是在构造方法执行过程当中完成的赋值。

实例变量默认值

byte short int long 0
float double 0.0
boolean false
char \u0000
引用数据类型 null

  • 实例变量是存储在JVM堆内存java对象内部

对象和引用的概念:

  • 对象:目前在使用new运算符在堆内存中开辟的内存空间称为对象
  • 引用:是一个变量,不一定是局部变量,还可能是成员变量。引用保存了内存地址,指向了堆内存当中的对象。
  • 所有访问实例相关的数据,都需要通过“引用.”的方式访问,因为只有通过引用才能找到对象
  • 只有一个空的引用,访问对象的实例相关的数据会出现空指针异常
class Student{

		Computer com; //com是一个引用【实例变量】

		public static void doSome(){
				Computer cc; //cc是一个引用【局部变量】
			}
		}
public class ConstructorTest02{
	public static void main(String[] args){
		//创建对象
		Account act1 = new Account();

		System.out.println("账号:"+act1.getAccount());//null
		System.out.println("余额:"+act1.getBalance());//0.0
		
		Account act2=new Account("110");
		
		System.out.println("账号:"+act2.getActno());//110
		System.out.println("余额:"+act2.getBalance());//0.0
		
		Account act3=new Account(10000.0);
		
		System.out.println("账号:"+act3.getActno());//null
		System.out.println("余额:"+act3.getBalance());//10000.0
		
		Account act4=new Account("act-001",10000.0);
		
		System.out.println("账号:"+act4.getActno());//act-001
		System.out.println("余额:"+act4.getBalance());//10000.0
		
		//通过调用不同的构造方法,传递不同的实参,在读取时,构造方法就会为实例变量赋值。相当于更改默认值
			
			
		}
}
//账户类
public class Account {

	//账号
	private String actno;
	
	//余额
	private double balance;

	//无参数构造器
	public Account() {
		//初始化实例变量的内存空间
		//actno=null;
		//balance=0.0;
	}
	
	public Account(String s) {
		actno = s;
	}

	public Account(double d) {
		balance = d;
	}
	
	public Account(String s, double d) {
		actno = s;
		balance = d;
	}

	public String getActno() {
		return actno;
	}

	public void setActno(String actno) {
		this.actno = actno;
	}

	public double getBalance() {
		return balance;
	}

	public void setBalance(double balance) {
		this.balance = balance;
	}
	
	
}

Java语言中,方法调用的时候涉及到参数传递的问题

参数传递实际上传递的是变量中保存的具体值。
int i =10;
add(i); 等同于add(10);

public class Test01 {

	public static void main(String[] args) {

		int i=10;
		add(i);//11 add方法调用的时候,传递的实际上只是10这个字面值
		System.out.println("main -->"+i);//10
	}
	
	public static void add(int i) {
		i++;
		System.out.println("add -->"+i);//11
	}

}

在这里插入图片描述

public class Test02 {

	public static void main(String[] args) {

		//通过调用有参数的构造方法来,创建一个User对象,并且给实例变量赋值。
		User u=new User(20);
		
		//传递的是什么?
		//传递的是main方法中u引用这个变量中保存的值,是一个内存地址。
		add(u);
		System.out.println("main -->"+u.age);//访问的是main方法中这个u引用的指向对象中实例变量age属性
		//由于在前面代码中,传递给add方法中,指向了同一个内存地址,虽然此时add方法执行结束后弹栈,但是在堆内存中
		//所做的对User对象实例变量的更改仍然保留。所以,在读取main方法中u引用指向的同一内存地址,也会受到影响。
		
		//始终牢牢记住,java中参数的传递都是变量中保存的“值”,无论它是字面值还是一个java对象的内存地址。
		//按照代码执行顺序,一步一步画图,理解本质的东西。
		//同时,局部变量本身也是有它自己的内存地址的,不要把它肚子中保存的内存地址给弄混淆。传递的是肚子里的“值”。
		
	}
	
	public static void add(User u) {
		u.age++;
		System.out.println("add -->"+u.age);//输出肯定是21
	}

}

class User{
	
	//实例变量age
	int age;
	
	//需要传递参数的构造方法
	public User(int i) {
		age=i;
	}
}

在这里插入图片描述
最终结论:
方法在调用的时候,涉及到参数传递的问题,传递的时候,java只遵循一种语法机制:

那就是将变量中保存的哪个“”给传过去了,只不过有时候这个值是字面值10,有的时候,这个值它是另外一个堆内存Java对象的内存地址0x1234。

下一篇:封装详解

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值