可变参数、作用域、构造方法/构造器


可变参数

基本概念

java 允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。
就可以通过可变参数实现

基本语法

访问修饰符 返回类型 方法名(数据类型… 形参名){
}

快速入门案例

看一个案例 类 HspMethod,方法sum[可以计算2个数的和,3个数的和,……]

public class VarParameter01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
            HspMethod m=new HspMethod();
           System.out.println(m.sum(1,5,100));//106
           System.out.println(m.sum(1,19));//20
	}

}
class HspMethod{
	//可以计算 2个数的和,3个数的和,4,5,..
	//可以使用方法重载
//	public int sum(int n1,int n2) {//2个数的和
//		return n1+n2;
//	}
//	public int sum(int n1,int n2,int n3) {//3个数的和
//		return n1+n2+n3;
//	}
//	public int sum(int n1,int n2,int n3,int n4) {//4个数的和
//		return n1+n2+n3+n4;
	//.....
	//上面的三个方法名称相同,功能相同,参数个数不同-> 使用可变参数优化
	//1.int..表示接受的是可变参数,类型是int,既可以接受多个int(0-多)
	//2.使用可变参数时
	//3.遍历nums 求和即可
	//}
	public int sum(int...nums) {
	//	System.out.println("接受的参数个数="+nums.length);
		int res=0;
		for(int i=0;i<nums.length;i++) {
			res+=nums[i];
		}
		return res;
	}
}

注意事项和使用细节

  1. 可变参数的实参可以为0个或任意多个
  2. 可变参数的实参可以为数组
  3. 可变参数本质就是数组
  4. 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
  5. 一个形参列表只能出现一个可变参数
public class VarParameterDetail {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//细节:可变参数的实参可以为数组
		int arr[]= {1,2,3};
		T t1=new T();
		t1.f1(arr);

	}

}
class T{
	public void  f1(int...nums) {
		System.out.println("长度="+nums.length);
		
	}
	//细节:可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
	public void f2(String d1,double...nums) {
		
	}
}

课堂练习

有三个方法,分别实现返回姓名和两门课成绩(总分),返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。封装成一个可变参数的方法

public class VarParameterExercise {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
        
		HspMethod01 hm=new HspMethod01();
		System.out.println(hm.showScore("milan", 90,80.0));
		System.out.println(hm.showScore("terry", 2.0,5,6,85,65));
	}

}
class HspMethod01{
	/*有三个方法,分别实现返回姓名和两门课程(总分)
	 * 返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分),
	 * 封装成一个可变参数的方法
	 */
	//分析1.方法名 showScore 2.形参(String,double...)3.返回String
	public String showScore(String name,double...scores) {
		double totalScore=0;
		for(int i=0;i<scores.length;i++) {
			totalScore +=scores[i];
		}
		return name+"有"+scores.length+"门科的成绩总分为"+totalScore;
	}
	
}

作用域

基本使用

  1. 在java编程中,主要的变量就是属性(成员变量)和局部变量。全局变量:也就是属性,作用域为整个类体Cat类:cry eat等方法使用属性
  2. 我们说的局部变量一般是指在成员方法中定义的变量。【举例Cat类:cry】
  3. java中作用域的分类
    1. 全局变量:也就是属性,作用域为整个类体Cat类:cry eat等方法使用属性
    2. 局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中
  4. 全局变量(属性)可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
public class VarScope01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
//1在java编程中,主要的变量就是属性
//2除了属性之外的其他变量,作用域为定义它的代码块中
//3全部变量(属性)可以不赋值,直接使用,因为有默认值,
//局部变量必须在赋值后,才能使用,因为没有默认值
//
class Cat{
	//全局变量:也就是属性,作用域为整个类体Cat类:cry eat 等方法的属性
	//属性在定义时,可以直接赋值
	
	int age =10;//指定的值是10
	double weight;//不赋值默认值是0.0
	{
		int num=100;//不是属性,在代码块里定义
	}
	public void hi() {
		//局部变量必须赋值才能使用,因为没有默认值
		//int num;×
		int num=1;
		String address ="北京的猫";
		System.out.println("address"+address);
		System.out.println("num="+num);
		System.out.println("weight"+weight);
	}
	public void cry() {
		
		//1.局部变量一般是指在成员方法中定义的变量
		//2.n和name都是局部变量
		//3.n和name的作用域在cry方法中
		int n=10;
		String name ="jack";
		
	}
	public void eat() {
		System.out.println("在eat方法中使用age="+age);
		//System.out.println("在eat方法中使用cry的变量"+name);不允许使用
	}
}

注意事项和细节使用

  1. 属性和局部变量可以重名,访问时遵循就近原则
  2. 在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名。
  3. 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁.即在一次方法调用过程中。
  4. 作用域范围不同
    1. 全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
    2. 局部变量:只能在本类中对应的方法中使用
  5. 修饰符不同
    1. 全局变量/属性可以加修饰符
    2. 局部不可以加修饰符
public class VarScopeDetail {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person p1=new Person();
		/*
		3.细节 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁
		 局部变量,生命周期较短,伴随着它的代码块的执行而创建
		 伴随着代码块的结束而销毁。即在一次方法调用过程中
		 */
		p1.say();//当执行say方法时,say方法的局部变量比如name,会创建,
		//当say执行完毕后,	
		//name局部变量被销毁,但是属性(全局变量)仍然可以使用
             T1 t1=new T1();
             t1.test();//第一种 跨类访问对象属性的方式
             t1.test2(p1);//第二种 跨类访问对象属性的方式
	}
}
class T1 {
	//4细节 全局变量(属性):可以被本类使用,或其他类使用(通过对象调用)
	public void test() {
		Person p1=new Person();
		System.out.println(p1.name);//jack
	}
	public void test2(Person P) {
		System.out.println(P.name);//jack
	}
}
class Person{
	//5细节 属性可以在前面加修饰符(public,protected,private..),局部不能加
	public int age=20;
	String name ="jack";
	public void say() {
		//1细节 属性和局部变量可以重名,访问时遵循就近原则
		//public String name="King"; × 不允许加修饰符
		String name="King";
		System.out.println("say()name="+name);//输出King
	}
	public void hi() {
		String address="北京";
		//String address="上海";×2细节 在一个方法中局部变量不能重名
		String name="frx";//ok的,在不同的作用域里面
	}
}

构造方法/构造器

看一个需求

我们来看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?这时就可以使用构造器。

基本语法

[修饰符] 方法名(形参列表){ 方法体; }

  • 说明
  1. 构造器的修饰符可以默认, 也可以是 public protected private
  2. 没有返回值
  3. 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化

快速入门

现在我们就用构造方法来完成刚才提出的问题:在创建人类的对象时,就直接指定这个对象的年龄和姓名

public class Constructor01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//当我们new一个对象时,直接通过构造器指定名字的年龄
     	Person  p1= new Person("smith",80);
     	System.out.println("p1的信息如下");
     	System.out.println("p1对象name="+p1.name);//smith
     	System.out.println("p1对象age="+p1.age);//80
	}

}

//在创建人类的对象时,就直接指定这个对象的年龄和姓名
//
class Person{
	String name;
	int age;
	//构造器
	//1.构造器没有返回值,也不能写void
	//2.构造器的名称和类Person一样
	//3.(String pName,int pAge)
	public Person(String pName,int pAge) {
		System.out.println("构造器被调用-完成对象的属性初始化");
		name =pName;
		age =pAge;
		
	}
}

注意事项和使用细节

  1. 一个类可以定义多个不同的构造器,即构造器重载
    比如:我们可以再给Person类定义一个构造器,用来创建对象的时候,只指定人名,不需要指定年龄
  2. 构造器要和类名相同
  3. 构造器没有返回值
  4. 构造器是完成对象的初始化,并不是创建对象
  5. 在创建对象时,系统自动的调用该类的构造方法
  6. 如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
  7. 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显示的定义一下。即Dog(){}
public class ConstructorDetail {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
      Person1 p1= new Person1("king",40);//第一个构造器
      Person1 p2=new Person1("tom");//第二个构造器
      Dog dog1=new Dog();
	}

}
class Dog{
	//如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
	//使用javap指令 反编译看看
	/*
	 默认构造器
	 Dog(){
	 
	 }
	 */
	public Dog(String dName) {
		
		
	}
	Dog(){//显示的定义一下 默认无参构造器
		
	}
}
class Person1{
	String name;
	int age;//默认0
	//第一个构造器
	public Person1(String pName,int pAge) {	
		name=pName;
		age=pAge;	
	}
	//第2个构造器,只指定人名,不指定年龄
	public Person1(String pName) {
		name=pName;
	}
	
}

课堂练习

在前面定义的 Person 类中添加两个构造器:
第一个无参构造器:利用构造器设置所有人的 age 属性初始值都为 18
第二个带 pName 和 pAge 两个参数的构造器:使得每次创建 Person 对象的同时初始化对象的 age 属性值和 name属性值
分别使用不同的构造器,创建对象.

public class ConstructorExercise {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
   		Person2 p1=new Person2();//无参构造器
   		System.out.println("p1的信息name="+p1.name+",age="+p1.age);
   		Person2 p2=new Person2("scott",50);
   		System.out.println("p2的信息name="+p2.name+",age="+p2.age);
	} 

}
/*
 第一个构造器:利用构造器设置所有人的age属性初始值为18
 第二个带pName和pAge两个参数的构造器:
 使得每次创建Person对象的同时初始化对象的age属性值和name属性值
 分别使用不同的构造器,创建对象
 */
class Person2{
	String name;//默认值 null
	int age;//默认值 0
	public Person2() {
		age=18;
	}
	public Person2(String pName,int pAge) {
		name=pName;
		age=pAge;
	}
	
} 

文章作者: Chtholly2333
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chtholly2333 !
  目录