前言:菜鸟一枚,如有问题欢迎大家在评论区指出,我们一起学习。
1.7.1:参数
方法的参数传递机制:实参给形参赋值,那么反过来形参会影响实参吗?在讨论这个问题之前,我们要先了解实例变量和局部变量的特点。
实例变量和局部变量的区别:
1、声明位置和方式
(1)实例变量:在类中方法外
(2)局部变量:在方法体{}中或方法的形参列表、代码块中
2、在内存中存储的位置不同
(1)实例变量:堆
(2)局部变量:栈
3、生命周期
(1)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡, 而且每一个对象的实例变量是独立的。
(2)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡, 而且每一次方法调用都是独立。
4、作用域
(1)实例变量:通过对象就可以使用,本类中“this.,没有歧义还可以省略this.”,其他类中“对象.” (2)局部变量:出了作用域就不能使用
5、修饰符
(1)实例变量:public,protected,private,final,volatile,transient等
(2)局部变量:final
6、默认值
(1)实例变量:有默认值
(2)局部变量:没有,必须手动初始化。其中的形参比较特殊,靠实参给它初始化。
形参是基础数据类型时:
形参方法的形参是基本数据类型时,形参值的改变不会影响实参;
原因:当形式参数为基本类型时,传递过来的是一个值。方法在调用后,会在栈空间开辟一个空间,创建一个局部变量,然后将接受到的值复制到形式参数的变量上,然后对其进行操作。在方法结束时,创建的局部变量也会消失.同时其原始数据并没有收到影响。
形参是引用数据类型时:
方法的形参是引用数据类型时,形参地址值的改变不会影响实参,但是形参地址值里面的数据的改变会影响实参,例如,修改数组元素的值,或修改对象的属性值。
String虽为引用数据类型,但是仍然属于值传递,即不会改变实参
原因:当形式参数为引用类型时,传递过来的值是一个堆内存的地址。调用方法后,系统会在栈空间开辟一个空间,创建一个对象,当接收到地址值后,会将刚创建的对象指向地址,然后方法对引用类型的操作实际上操作的是在堆空间存放的原始数据。当方法结束后,方法中创建的对象排队释放,而原始的引用类型依然指向堆空间,所以原始数据发生了变化。
public class SomeObject {
//基础数据类型传参传的是值
public void methodOne(int one, int two) {
System.out.println("one = " + one + ", two = " + two);
int temp;
temp = one;
one = two;
two = temp;
System.out.println("one = " + one + ", two = " + two);
}
//引用数据类型传的参是地址
public void methodTwo(MyNumber mn) {
System.out.println("mn.one = " + mn.one+ ", mn.two = " + mn.two);
int temp;
temp = mn.one;
mn.one = mn.two;
mn.two = temp;
System.out.println("mn.one = " + mn.one+ ", mn.two = " + mn.two);
}
}
class MyNumber{
int one;
int two;
}
public class TestSomeObject {
public static void main(String[] args) {
SomeObject so = new SomeObject();
int yi =100;
int er =200;
System.out.println("yi = "+yi+",er = "+er);
System.out.println("-------------method---------");
so.methodOne(yi,er);
System.out.println("--------------main--------");
System.out.println("yi = "+yi+",er = "+er);
System.out.println("----------------------------------------------------------");
MyNumber mn = new MyNumber();
mn.one = 100;
mn.two = 200;
System.out.println("mn.one = " + mn.one+", mn.two = " + mn.two);
System.out.println("------------method------------");
so.methodTwo(mn);
System.out.println("------------main-----------");
System.out.println("mn.one = " + mn.one+", mn.two = " + mn.two);
}
}
运行结果:
特殊参数:可变参数组
在JDK1.5之后,当定义一个方法时,形参的类型可以确定,但是形参的个数不确定,那么可以考虑使用可变参数。
可变参数的特点和要求:
(1)一个方法最多只能有一个可变参数
(2)如果一个方法包含可变参数,那么可变参数必须是形参列表的最后一个
(3)在声明它的方法中,可变参数当成数组使用
public class TestSomeObject {
public static void main(String[] args) {
SomeObject someObject = new SomeObject();
//方法带有变长参数组时,在传参时可以传一个,可以不传,也可以有几个传几个,参数之间用逗号隔开
//和普通参数一起使用时,普通参数必须要传
someObject.method("value",200,300);
}
}
public class SomeObject {
//变长参数组
//一个方法的参数列表中,只能由一个变长参数组
//边长参数组可以和普通参数一起使用,但是变长参数组必须放在参数组的最后面
public int method(String a, int b, int... nums) {
int result =0;
//变长参数组就是一个数组
for (int i = 0; i < nums.length; i++) {
result += nums[i];
}
return result;
}
}
1.7.2:方法的重载
指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。
参数列不同:参数列表:数据类型个数不同,数据类型不同(按理来说数据类型顺序不同也可以,但是很少见,也不推荐,逻辑上容易有歧义)。
public class SomeObject {
//方法的重载发生在同一个类中
//在同一个类中 方法名相同,参数组不同(参数个数,参数类型,参数顺序)就构成了方法的重载
//最熟悉的一个方法重载就是println,根据不同的参数输出不同类型的参数
public void methodOne() {
System.out.println("SomeObject.methodOne()");
}
public void methodOne(int a) {
System.out.println("SomeObject.methodOne(int)");
}
}
1.7.3:对象数组
对象数组的概念:
如果一个数组中的元素是对象类型,则称该数组为对象数组。当需要一个类的多个对象时,应该用该类的对象数组来表示,通过改变下标值就可以访问到不同的对象。
对象数组的定义和使用:
对象数组的定义与一般数组的定义类似,但是需要为每一个元素实例化。当然,声明和创建可以一起进行。
public class Student {
String name;
int age;
String gender;
public void sayHello() {
System.out.println("my name is " + name+", my age is "+age+", my gender is "+gender);
}
}
public class TestStu {
public static void main(String[] args) {
//创建一个对象数组
Student[] students = new Student[2];
students[0] = new Student();
students[0].name = "Tom";
students[0].age = 18;
students[0].gender = "男";
students[1] = new Student();
students[1].name = "Jack";
students[1].age = 19;
students[1].gender = "女";
for (int i = 0; i < students.length; i++) {
students[i].sayHello();
}
}
}
判断对象是否属于某个类java如何判断一个对象是否属于某个类 | PingCode智库
对象数组的另一种赋值方式创建对象数组,给数组赋值(两种理解思路) - 萧然成长记 - 博客园 (cnblogs.com)
1.7.4:构造器
我们发现我们new完对象时,所有成员变量都是默认值,如果我们需要赋别的值,需要挨个为它们再赋值,太麻烦了。我们能不能在new对象时,直接为当前对象的某个或所有成员变量直接赋值呢。可以,Java给我们提供了构造器(Constructor)。
构造器的创建:
public class Student {
String name;
int age;
String gender;
//一个类中没有显式的构造器,则系统自动创建一个隐式的无参的构造器
//构造器与类同名,没有返回值
public Student() {
}
//创建有参构造器(隐式构造器自动消失,不能使用new Student(),则需要重新创建一个隐式)
public Student(String name, int age, String gender){
//局部变量和属性重名是允许的,在访问时优先访问局部变量
//此时访问属性需要用this
this.name = name;
this.age = age;
this.gender = gender;
}
public void sayHello() {
System.out.println("my name is " + name+", my age is "+age+", my gender is "+gender);
}
}
构造器的使用:
public class TestStudent {
//创建对象必须需要一个构造器,构造器只在创建对象时使用
public static void main(String[] args) {
// Student()就是一个无参构造器
Student s1 = new Student();
//使用定义的有参构造器
Student s2 = new Student("Tom", 18, "男");
s2.sayHello();
}
}