学习-Java类和对象之参数传值机制之求球面积

第1关:学习-Java类和对象之参数传值机制之求球面积


任务描述

本关任务:已知一个球的半径为 12.0,求该球的表面积。

球的表面积计算公式:S=4\pi R^2S=4πR2,RR为球的半径。

相关知识

为了完成本关任务,你需要掌握:

  1. 基本数据类型参数的传值;
  2. 引用类型参数的传值;

形参和实参

我们知道,在 Java 中定义方法时,是可以定义参数的,比如:

 
  1. public static void main(String[] args){
  2. }

这里的 args 就是一个字符串数组类型的参数。

在程序设计语言中,参数有形式参数和实际参数之分,先来看下它们的定义:

  • 形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数,简称“形参”;

  • 实际参数:在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”,简称“实参”。

举个栗子:

 
  1. public class Demo {
  2. public static void main(String[] args) {
  3. Demo demo = new Demo();
  4. // 实际参数为“张三”
  5. demo.fun("张三");
  6. }
  7. public void fun(String name) {
  8. // 形式参数为 name
  9. System.out.print(name);
  10. }
  11. }

上面例子中,Demo 类中定义了一个 fun 方法,该方法有个 String 类型的参数 name,该参数即为形参。在 main 方法中,调用了 main 方法,传入了一个参数“张三”,该参数即为实参。

那么,实参值是如何传入方法的呢?这是由方法的参数传递机制来控制的。

值传递和引用传递

参数传递机制有两种:值传递和引用传递。我们先来看下程序语言中是如何定义和区分值传递和引用传递的:

  • 值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数;

  • 引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

那么,在参数传递时,如何区分使用的是值传递还是引用传递? Java 中方法参数共有两种类型:

  • 基本数据类型;
  • 引用数据类型。

首先我们来看基本数据类型的传值。

基本数据类型参数的传值

例子:

 
  1. public class Demo {
  2. public static void main(String[] args) {
  3. Demo demo = new Demo();
  4. int i = 10;
  5. System.out.println("pass方法调用前,i的值为=" + i);
  6. demo.pass(i);
  7. System.out.print("pass方法调用后,i的值为=" + i);
  8. }
  9. public void pass(int i) {
  10. i *= 3;
  11. System.out.println("pass方法中,i的值为=" + i);
  12. }
  13. }

上面代码中,我们在类中定义了一个 pass 方法,方法内部将传入的参数 i 的值增加至 3 倍,然后分别在 pass 方法和 main 方法中打印参数的值,执行结果:

 
  1. pass方法执行前,i的值为=10
  2. pass方法中,i的值为=30
  3. pass方法执行后,i的值为=10

从上面运行结果来看,pass 方法中,i 的值是 30,pass 方法执行结束后,变量 i 的值依然是 10。

可以看出,main 方法里的变量 i,并不是 pass 方法里的 i,pass 方法内部对 i 的值的修改并没有改变实际参数 i 的值,改变的只是 pass 方法中 i 的值(pass 方法中,i=30),因为 pass 方法中的 i 只是 main 方法中变量 i 的复制品。

因此很容易得出结论:在 Java 中,一个方法不可能修改一个基本数据类型的参数 ,所以是值传递。

引用类型参数的传值

上面介绍的是基本数据类型的参数传递,那对于引用数据类型,参数传递又是怎么样的呢?先来看以下代码:

 
  1. public class Demo {
  2. public static void main(String[] args) {
  3. Demo p = new Demo();
  4. User user = new User();
  5. user.name="张三";
  6. user.age=18;
  7. System.out.println("pass方法调用前,user=" + user.toString());
  8. p.pass(user);
  9. System.out.println("pass方法调用后,user=" + user.toString());
  10. }
  11. public void pass(User user) {
  12. user.name="李四";
  13. System.out.println("pass方法中,user = " + user.toString());
  14. }
  15. }
  16. class User {
  17. String name;
  18. int age;
  19. @Override
  20. public String toString() {
  21. return "User{" +
  22. "name='" + name + '\'' +
  23. ", age=" + age +
  24. '}';
  25. }
  26. }

上面代码中,定义了一个 User 类,在 main 方法中,new 了一个新的 User 对象 user,然后给 user 对象的成员变量赋值,pass 方法中,修改了传入的 user 对象的属性。

执行结果:

 
  1. pass方法调用前,user= User{name='张三', age=18}
  2. pass方法中,user = User{name='李四', age=18}
  3. pass方法调用后,user= User{name='李四', age=18}

经过 pass 方法执行后,实参的值竟然被改变了!!!那按照上面的引用传递的定义,实际参数的值被改变了,这不就是引用传递了么?

难道在 Java 的方法中,在传递基本数据类型的时候是值传递,在传递引用数据类型的时候是引用传递?

其实不然,Java 中传递引用数据类型的时候也是值传递。

为什么呢?先给大家说一下概念中的重点:

值传递,是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递,是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

两者的区别如下:

值传递引用传递
根本区别会创建副本不会创建副本
影响结果函数中无法改变原始对象函数中可以改变原始对象

复制的是参数的引用(地址值),并不是引用指向的存在于堆内存中的实际对象。

main 方法中的 user 是一个引用(也就是一个指针),它保存了 User 对象的地址值,当把 user 的值赋给 pass 方法的 user 形参后,即让 pass 方法的 user 形参也保存了这个地址值,即也会引用到堆内存中的 User 对象。

上面代码中,之所以产生引用传递的错觉,是因为参数保存的是实际对象的地址值,你改变的只是地址值指向的堆内存中的实际对象,并没有真正改变参数,参数的地址值没有变。

下面结合生活中的场景,再来深入理解一下值传递和引用传递。

你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你会看到钥匙上有他的名字。

你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,旧钥匙还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。

但是,不管上面哪种情况,你的朋友拿着你给他的钥匙,进到你的家里,假如把你家的电视砸了,那你说你会不会受到影响?

我们在 pass 方法中,改变 user 对象的 name 属性的值的时候,不就是在“砸电视”么。你改变的不是那把钥匙(地址值),而是钥匙打开的房子(地址值对应的实际对象)。

那我们怎样才能真正的改变参数呢,看如下代码:

 
  1. public class Demo {
  2. public static void main(String[] args) {
  3. Demo p = new Demo();
  4. User user = new User();
  5. user.name = "张三";
  6. user.age = 18;
  7. System.out.println("pass方法调用前,user=" + user.toString());
  8. p.pass(user);
  9. System.out.println("pass方法调用后,user=" + user.toString());
  10. }
  11. public void pass(User user) {
  12. user = new User();
  13. user.name = "李四";
  14. user.age = 20;
  15. System.out.println("pass方法中,user = " + user.toString());
  16. }
  17. }
  18. class User {
  19. String name;
  20. int age;
  21. @Override
  22. public String toString() {
  23. return "User{" +
  24. "name='" + name + '\'' +
  25. ", age=" + age +
  26. '}';
  27. }
  28. }

在这段代码中,pass 方法中,我们真正的改变了 user 参数,因为它指向了一个新的地址(user = new User()),即参数的地址值改变了。执行结果:

 
  1. pass方法调用前,user= User{name='张三', age=18}
  2. pass方法中,user = User{name='李四', age=20}
  3. pass方法调用后,user= User{name='张三', age=18}

从结果看出,虽然 pass 对参数进行了修改,但是没有影响到实际参数。

所以说,Java 中其实还是值传递的,只不过对于引用类型参数,值的内容是对象的引用。

编程要求

仔细阅读右侧编辑区内给出的代码框架及注释,按照提示编写程序代码。

测试说明

平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。 可在右侧“测试结果”区查看具体的测试集详情。


开始你的任务吧,祝你成功!

/**
 * 任务:已知一个球的半径为 12.0,求该球的表面积。
 * 类名为:Sphere
 */
public class Sphere {
// 请在下面的Begin-End之间按照注释中给出的提示编写正确的代码
/********** Begin **********/
    // 定义圆的半径和π,π为 Math中的π
double r;
    // 无参构造
Sphere(){
    
}
    // 有参构造
Sphere(double r){
    this.r=r;
}
    /**
     * 定义一个方法,该方法实现计算球的表面积,返回值为double,携带一个参数,为球的半径
     */
public static double mian(double r){
    return 4*(Math.PI)*r*r;
}
    // 定义主方法
public static void main(String[] args){
    // 通过无参构造创建球对象
Sphere sphere=new Sphere();
    // 调用计算球面积的方法,将半径 r 的值传入
double result = sphere.mian(12.0);
    // 四舍五入格式化不换行输出球的面积,输出格式:球的表面积为xx
System.out.print("球的表面积为"+ String.format("%.2f",result));
}
/********** End **********/

}

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java中的类和对象之间的参数传递采用的是值传递机制。这意味着,在调用方法时,实际上是将参数值的副本传递给方法,而非原始参数本身。因此,在方法内对参数的更改不会影响到原始参数。 计算球面积的公式是 4πr²。 因此,我们可以定义一个名为 "sphereArea" 的方法,该方法接收一个double类型的参数"r",并返回该球体的面积。 代码示例: ``` public class Sphere { public static double sphereArea(double r) { return 4 * Math.PI * r * r; } public static void main(String[] args) { double radius = 5; double area = sphereArea(radius); System.out.println("The area of sphere is: " + area); } } ``` 运行结果: ``` The area of sphere is: 314.1592653589793 ``` ### 回答2: 在Java中,参数传值机制指的是将一个参数的值从一个方法或函数传递到另一个方法或函数的过程。Java中有两种传参的方式:传值调用和传引用调用。 在传值调用中,当一个实参传递给一个方法参数时,方法接收到的是实参的副本而不是实参的引用,这意味着方法中对参数的任何修改都不会影响原始调用者。在传引用调用中,方法接收到的是实参的引用而不是副本,这意味着方法中对参数的任何修改都会影响原始调用者。 如果我们用Java类和对象来求球的面积,我们可以定义一个Sphere类,该类具有半径属性、圆周率属性和求圆面积的方法。 首先我们需要定义一个Sphere类,包含半径属性和圆周率属性,代码如下: public class Sphere { private double radius; private final double PI = Math.PI; public Sphere(double r) { this.radius = r; } public double getRadius() { return radius; } public double getPI() { return PI; } } 接下来,我们需要在Sphere类中定义一个方法来获取球的面积,代码如下: public double getArea() { return 4 * PI * Math.pow(radius, 2); } 这个方法使用圆周率(Math.PI)和半径(radius)属性来计算球的面积,并返回结果。 现在我们来看看如何使用这个方法来计算球面积,并显示结果。我们需要创建一个Sphere对象并向其传递半径值,代码如下: Sphere mySphere = new Sphere(2.5); 然后我们可以使用该对象的getArea()方法来获取球的面积值,代码如下: double area = mySphere.getArea(); 最后,我们可以将结果打印到屏幕上,代码如下: System.out.println("The area of the sphere is: " + area); 这样就可以通过JAVA类和对象来计算球面积了。需要注意的是,在这个过程中,我们使用的是传值调用机制,因为我们传递的是半径值,而不是对象的引用。 ### 回答3: 在Java中,我们可以通过类和对象来实现各种功能。而在类和对象的使用过程中,参数传值机制是一个非常重要的概念。 所谓参数传值机制,就是在调用一个函数的过程中,将实参的值传递给形参的过程。在Java中,有两种参数传递机制,分别是值传递和引用传递。值传递就是将实参的值复制给形参,形参和实参是两个不同的变量。而引用传递则是将实参的地址复制给形参,形参和实参指向同一个变量。 举个例子来说,在求球面积的过程中,我们可以定义一个球的类,并在该类中定义一个方法来计算球的面积。这个方法需要接收球的半径作为参数。在调用该方法的时候,可以使用值传递或引用传递来传递半径值。 如果使用值传递,那么就需要将球的半径值复制给方法参数,如下所示: ``` class Sphere { public static double area(double radius) { return 4 * Math.PI * radius * radius; } } // 调用求球面积方法 double radius = 5.0; double area = Sphere.area(radius); ``` 如果使用引用传递,那么就需要将球的半径值的地址传递给方法参数,如下所示: ``` class Sphere { double radius; public Sphere(double radius) { this.radius = radius; } public double area() { return 4 * Math.PI * radius * radius; } } // 调用求球面积方法 Sphere sphere = new Sphere(5.0); double area = sphere.area(); ``` 无论使用哪种参数传递机制,都可以求出球的面积。但在不同的情况下,选择不同的参数传递方式会更加高效和方便。 总之,在学习Java类和对象中,理解参数传值机制是非常重要的一步。只有深入理解参数传递机制,才能更好地开发出高效可靠的Java程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值