可变参数
基本概念
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;
}
}
注意事项和使用细节
- 可变参数的实参可以为0个或任意多个
- 可变参数的实参可以为数组
- 可变参数本质就是数组
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
- 一个形参列表只能出现一个可变参数
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;
}
}
作用域
基本使用
- 在java编程中,主要的变量就是属性(成员变量)和局部变量。全局变量:也就是属性,作用域为整个类体Cat类:cry eat等方法使用属性
- 我们说的局部变量一般是指在成员方法中定义的变量。【举例Cat类:cry】
- java中作用域的分类
- 全局变量:也就是属性,作用域为整个类体Cat类:cry eat等方法使用属性
- 局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中
- 全局变量(属性)可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
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);不允许使用
}
}
注意事项和细节使用
- 属性和局部变量可以重名,访问时遵循就近原则。
- 在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名。
- 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁.即在一次方法调用过程中。
- 作用域范围不同
- 全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
- 局部变量:只能在本类中对应的方法中使用
- 修饰符不同
- 全局变量/属性可以加修饰符
- 局部不可以加修饰符
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的,在不同的作用域里面
}
}
构造方法/构造器
看一个需求
我们来看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?这时就可以使用构造器。
基本语法
[修饰符] 方法名(形参列表){ 方法体; }
- 说明
- 构造器的修饰符可以默认, 也可以是 public protected private
- 没有返回值
- 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化
快速入门
现在我们就用构造方法来完成刚才提出的问题:在创建人类的对象时,就直接指定这个对象的年龄和姓名
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;
}
}
注意事项和使用细节
- 一个类可以定义多个不同的构造器,即构造器重载
比如:我们可以再给Person类定义一个构造器,用来创建对象的时候,只指定人名,不需要指定年龄 - 构造器要和类名相同
- 构造器没有返回值
- 构造器是完成对象的初始化,并不是创建对象
- 在创建对象时,系统自动的调用该类的构造方法
- 如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
- 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显示的定义一下。即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;
}
}