12.23_学习Java的day07(详解)

成员变量和成员方法的使用:

1、在其他类中

(1)成员变量
①静态
类名.静态变量
对象名.静态变量
匿名对象.静态变量
②非静态
对象名.实例变量
匿名对象.实例变量
(2)成员方法
①静态
类名.静态方法(【实参列表】)
对象名.静态方法(【实参列表】)
匿名对象.静态方法(【实参列表】)
②非静态
对象名.实例方法(【实参列表】)
匿名对象.实例方法(【实参列表】)

2、在本类中

(1)成员变量
①静态
静态的方法中,可以直接使用本类的静态变量
非静态的方法中,可以直接使用本类的静态变量

②非静态
在本类的静态方法中,无法直接使用本类的非静态的成员变量
在本类的非静态方法中,可以直接使用本类的非静态的成员变量

(2)成员方法
①静态
静态的方法中,可以直接调用本类的静态方法
非静态的方法中,可以直接调用本类的静态方法

②非静态
在本类中的静态方法中,无法直接调用本类的非静态的成员方法
在本类的非静态方法中,可以直接调用本类的非静态的成员方法

结论:
在静态方法中,无法直接使用本类的非静态的成员变量和成员方法

静态  	用  静态		可以
静态  	用 	非静态		不行
非静态  用 	静态		可以
非静态  用 	非静态		可以
class FieldMethodUse{
	int a;
	static int b;
	public static void main(String[] args){
		//System.out.println("a = " + a);//错误: 无法从静态上下文中引用非静态 变量 a
		//System.out.println("b = " + b);//静态方法中,直接访问本类的静态变量  OK
		
		//test();//错误: 无法从静态上下文中引用非静态 方法 test()  NO
		//method();//静态方法中,直接访问本类的静态方法  OK
		
		Circle c = new Circle();
		c.radius = 1.2;
		//String info = c.getInfo();
		//System.out.println(info);
		
		System.out.println(c.getInfo());
	}
	
	public void test(){
		System.out.println("a = " + a);//非静态方法,直接访问本类的非静态变量  OK
		System.out.println("b = " + b);//非静态方法,直接访问本类的静态变量    OK
	}
	public void fun(){
		test();//非静态方法,直接访问本类的非静态方法  OK
		method();//非静态方法,直接访问本类的静态方法  OK
	}
	public static void method(){
		
	}
}
class Circle{
	static String name = "圆";
	double radius;
	
	//声明一个求面积的方法
	/*
	修饰符:要不要静态?
		如果是静态的,就是所有对象相同,面积,每一个圆对象不同,所以不同用静态的
	返回值类型:需要返回面积的值,double
	方法名:getArea
	(形参列表):是否需要调用者给你传递参数,这个参数是用于完成方法的功能,不需要
	功能:求面积
	*/
	double getArea(){
		return Math.PI * radius * radius;
	}
	
	//声明一个方法,可以返回圆的信息
	//例如:图形名:xx,半径:xx,面积:xx
	/*
	修饰符:要不要静态?
		每一个圆的信息不同,不能用静态的
	返回值类型:拼接结果,String
	方法名:getInfo
	(形参列表):是否需要调用者给你传递参数,这个参数是用于完成方法的功能,不需要
	*/
	String getInfo(){
		return "图形名:" + name + ",半径:" + radius + ",面积:"+ getArea();
	}
	
}


一、方法调用的内存分析(理解)

方法不调用不执行,调用一次执行一次,
每次调用会在栈中有一个入栈动作,
即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值等,
当方法执行结束后,会释放该内存,称为出栈,
如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,
回到调用处继续执行下一条指令。

class MethodInvoke{
	public static void main(String[] args){
		System.out.println(max(3,5));
		System.out.println(max(4,3));
	}
	
	public static int max(int a, int b){
		return a > b ? a : b;
	}
}

二、方法的参数传递机制(理解,重要,会分析,会做面试题)

1、分清楚参数:

形参:声明方法的()
实参:调用方法的()

2、 分清楚谁给谁传值:实参给形参传值

3、传的是什么值?

(1)形参是基本数据类型,实参给形参的是数据的值,
然后形参的修改,和实参无关

class PassParamValue{
	public static void main(String[] args){
		int num = 1;
		change(num);
		System.out.println("num = " + num);//num= 1
	}
	
	public static void change(int a){
		a = 2 * a;//形参a的值修改了,和num实参无关
	}
}

(2)形参是引用数据类型,实参给形参的是地址值,
然后形参通过这个地址,修改了这个对象在堆中成员变量/元素的值,或者在方法区的静态变量的值,
都会影响实参。
因为此时形参和实参指向了同一个堆中的对象。

class PassParamValue2{
	public static void main(String[] args){
		MyData m = new MyData();
		m.x = 1;
		
		change(m);
		
		System.out.println(m.x);//2
	}
	
	public static void change(MyData my){//形参是引用数据类型
		my.x = 2 * my.x;		
	}
}
class MyData{
	int x;
}

面试题:

希望打印结果:
x = 2;
y = 1;

public class PassParamExer2{
	public static void main(String[] args){
		int x = 1;
		int y = 2;
		
		method(x,y);
		
		System.out.println("x = " + x);
		System.out.println("y = " + y);
	}
	
	//请编码method()方法的代码,实现上面的效果
	public static void method(int x, int y){
		int temp = x;
		x = y;
		y = temp;
		
		System.out.println("x = " + x);
		System.out.println("y = " + y);
		
		System.exit(0);//退出JVM,结束程序的运行,使得main中的两个打印语句不执行
	}
	/*
	//失败
	public static void method(int x, int y){
		int temp = x;
		x = y;
		y = temp;
	}
	*/
}

方法参数传递的机制:值传递

(1)形参是基本数据类型:

实参给形参传递的是数据值,形参的修改不影响实参

(2)形参是引用数据类型:

实参给形参传递的是地址值,形参通过这个地址值修改了堆中对象的成员变量/元素的值,影响实参。

关于引用数据类型,问题/陷阱:
(1)形参 = new 类名();
即形参指向了新的对象,和实参就无关了

class PassParamProblem1{
	public static void main(String[] args){
		MyData m = new MyData();
		m.x = 1;
		
		change(m);
		
		System.out.println("m.x = " + m.x);//1
	}
	
	public static void change(MyData my){//形参是引用数据类型
		my = new MyData();
		my.x = 2 * my.x;
	}
}
class MyData{
	int x;
}

(2)形参是String、Integer等类型时,
无论形参怎么修改都和实参无关。

因为String、Integer等类型是不可变对象类型,只要修改就会产生新对象。

class PassParamProblem2{
	public static void main(String[] args){
		String s = "hello";
		change(s);
		System.out.println("s = " + s);//s = hello
	}
	
	public static void change(String str){
		str = str + "atguigu";// str = new String(str +"atguigu");
	}
}

变量的分类:

1、成员变量

(1)静态变量
(2)实例变量

2、局部变量

区别:

1、声明位置和方式

(1)静态变量:在类中方法外,并且有static修饰
(2)实例变量:在类中方法外,没有static修饰
(3)局部变量:在方法体{}中或方法的形参列表、代码块中

2、在内存中存储的位置不同

(1)静态变量:方法区
(2)实例变量:堆
(3)局部变量:栈

3、生命周期

(1)静态变量:和类的生命周期一样,因为它的值是该类所有对象共享的,早于对象的创建而存在。
(2)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡,
而且每一个对象的实例变量是独立的。
(3)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡,
而且每一次方法调用都是独立。

4、作用域

(1)静态变量和实例变量:不谈作用域
在本类中,唯一的限制,静态方法或静态代码块中不能使用非静态的,其他都可以直接使用。
在其他类中,能不能使用看修饰符(public,protected,private等)
(2)局部变量:有作用域
出了作用域就不能使用

5、修饰符(后面来讲)

(1)静态变量:很多
public,protected,private,final,volatile等,一定有的是static
(2)实例变量
public,protected,private,final,volatile,transient等
(3)局部变量
final

public,protected,private:权限修饰符
final:是否是常量,即值是否可以修改
volatile:和多线程有关
transient:是否序列化,和IO有关

6、默认值

(1)静态变量:有默认值
(2)实例变量:有默认值
(3)局部变量:没有,必须初始化
其中的形参比较特殊,靠实参给它初始化。

参数:形参和实参

三、可变参数:JDK1.5开始

1、什么是可变参数?

它仍然是形参和实参,只不过它是特殊的形参,形如:数据类型… 形参名

2、什么情况下使用形参

当我们在设计一个方法的时候,发现这个方法需要形参,
而且形参的类型可以确定,但是形参的个数不能确定时,就可以使用可变参数。
例如:当我们要设计方法,这个方法可以求任意个整数的和

3、如何使用可变参数?

(1)在设计可变参数的方法中,如何使用可变形参?
把它当做数组使用
(2)在调用时,
①可变形参对应的位置,可以传入0~n个对应类型的实参。
②可变形参对应的位置,可以传入对应类型的数组

4、需要注意的地方

(1)一个方法最多只能有一个可变参数
(2)可变参数必须是最后一个

class VarParam{
	public static void main(String[] args){
		System.out.println(sum());//传了0个实参
		System.out.println(sum(4));//传了1个实参
		System.out.println(sum(4,1,2,6,8));//传了5个实参
		
		int[] arr = {1,2,3,4,5};
		System.out.println(sum(arr));//传入一个数组
		
		System.out.println("--------------------------");
		//System.out.println(max());//错误的
		System.out.println(max(4,1,2,6,8));
	}
	
	//这个方法可以求任意个整数的和
	/*
	返回值类型:
		需要,结果是和,long
	方法名:sum
	形参列表:是否需要调用者给我们传递参数,需要,什么类型,int,几个?不知道
	*/
	static long sum(int... nums){
		long he = 0;
		for(int i=0; i<nums.length; i++){
			he += nums[i];
		}
		return he;
	}
	
	//这个方法可以求1-n个整数的最大值
	/*
	返回值类型:int
	方法名:max
	形参列表:至少需要调用者给我传入1个整数
	其中int num不是可变参数,
		int... args是可变参数
		调用时,非可变参数,原来该咋传咋传。
				可变参数部分,想咋传咋传,可以传入0~n个对应类型的实参也可以传入对应的数组
	*/
	static int max(int num, int... args){
		int biggest = num;
		for(int i=0; i<args.length; i++){
			if(biggest < args[i]){
				biggest = args[i];
			}
		}
		return biggest;
	}
}

形参、实参、可变参数

四、命令行参数:(了解)

1、特殊的形参和实参,它是main方法的形参和实参。
main方法的形参:(String[] args) 或 (String… args)

2、在main中如何使用args,把它当做数组使用

3、如何给main方法传实参
在运行时传入
格式:
java 类名 参数1 参数2 参数3 。。。

class CommandParam{
	public static void main(String[] args){
		System.out.println("args.length = " + args.length);
		for(int i=0; i<args.length; i++){
			System.out.println("第" + (i+1) + "个实参是:" + args[i]);
		}
	}
}

五、方法的重载:Overload

1、定义:

在一个类中,出现了两个或多个的方法,
它们的方法名称相同(因为它们的功能相同),
但是它们的形参列表不同(它们适用于不同的情况),
这样的两个或多个方法就构成了方法的重载。
和返回值类型无关。

class Overload{
	
	public static void main(String[] args){
		System.out.println(max(4,6));
		System.out.println(max(4.0,6.0));
		System.out.println(max(4,5,6));
		
		System.out.println(max(4,6.0));//找兼容的
	}
	
	//适用于两个整数求最大值
	public static int max(int a ,int b){
		System.out.println("两个整数的");
		return a > b ? a : b;
	}
	
	//适用于两个小数求最大值
	public static double max(double a ,double b){
		System.out.println("两个小数的");
		return a > b ? a : b;
	}
	
	public static int max(int a ,int b,int c){
		//int max = a > b ? a : b;
		//return max > c ? max : c;
		System.out.println("三个整数的");
		//先用上面的max(a,b)求出a,b的最大值,在用这个最大值和c用上面的max求出最大值
		return max(max(a,b),c);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值