java代码review收获_Java Review (七、面向对象----方法深入)

@

方法是类或对象的行为特征的抽象,方法是类或对象最重要的组成部分, 但从功能上来看,方法完

全类似于传统结构化程序设计里的函数 值得指出的是, Java里的方法不能独立存在 ,所有的方法都必须定义在类里 ,方法在逻辑上要么属于类,要么属于对象。

方法的所属性

不论是从定义方法的语法来看,还是从方法的功能来看都不难发现方法和函数之间的相似性,实际上,方法确实是由传统的函数发展而来的,方法与传统的函数有着显著不同:

在结构化编程语言里,函数是一等公民,整个软件由 一个个的函数组成

在面向对象编程语言里,类才是一等公民,整个系统由一个个的类组成

在 Java 方法不能独立存在,方法必须属于类或对象,如果需要定义方法,则只能在类体内定义,不能独立定义个方法。

一旦将一个方法定义在某个类的类体内:

如果这个方法使用了 static修饰 ,则这个方法属于这个类,

如果没有使用static修饰则这个方法属于这个类的实例。

Java语言是静态的。一个类定义完成后,只要不再重新编译这个类文件,该类和该类的对象所拥有的方法是固定的,永远都不会改变。

方法不能独立存在,所以方法也不能像函数那样被独立执行,执行方法时必须使用类或对象来作为调用者 ,即所有方法都必须使用类.方法 或 对象.方法 的形式来调用 。

这里可能产生 个问题: 同一个类里不同方法之间相互调用时,不就可以直接调用吗?这里需要指出:同 一个类的一个方法调用另外 个方时,如果被调方法是普通方法, 默认使用this 作为调用者;如果被调方法是静态方法,则默认使用类作为调用者。也就是说,表面上看起来某些方法可以被独立执行,但实际上还是使用 this 或者类来作为调用者。

方法属性总结:

方法不能独立定义,方法只 能在类体里定

从逻辑意义上来看,方法要么属于该类本身,要么属于该类 个对象

永远不能独立执行方法,执行方法必须使用类或对象作为调用者

使用 static 修饰的方法属于这个类本身,使用 static 修饰的方法既可以使用类作为调用者来调用,可以使用对象作为调用者来调用。但是因为使用 static 修饰方法还是属于这个类的,因此使用该类的任何对象来调用这个方法时将会得到相同的执行结果,这是由底层依然是使用这些实例所属的类作为调用者。没有 static 修饰的方法属于该类的对象,不属于这个类本身。因此没有 static 饰的方法只能使用对象作为调用者来调用,不能使用类作为调用者来调用 。使用不同对象作为调用者来调用同 一个普通方法,可能得到不同的结果。

方法的参数传递机制

前面己经介绍了 Java 里的方法是不能独立存在的,调用方法也必须使用类或对象作为主调者果声明方法时包含了形参声明,则调用方法时必须给这些形参指定参数值,调用方法时实际传给形参的参数值也被称为实参。

那么, Java 的实参值是如何传入方法的呢?这是由 Java 方法的参数传递机制来控制的, Java 里方法参数传递方式只有一种值传递。所谓值传递,就是将实际参数值的副本(复制品)传入方法内,而参数本身不会受到任何影响。

Java 里的参数传递类似于《西游记》里的孙悟空,孙悟空复制个假孙悟空,这个假孙悟空具有和孙悟空相同的能力,可除以被砍头 但不管这个假孙悟空遇到什么事,孙悟空不会受到任何 与此类似,传入方法的是实际参数值的复制品,不管方法中对这个复制品如何操作,实际参数值本身不会受到任何影响。

基本类型的参数传递

方法参数传递效果实例

public class PrimitiveTransferTest {

public static void swap(int a, int b) {

// 下面三行代码实现 的值交换

// 定义一个临时变量来保存a的值

int tmp = a;

// a的值赋给b

a = b;

// 把临时变量 tmp的值赋给b

b = tmp;

System.out.println("swap方法里,a的值是" + a + "; b的值是" + b);

}

public static void main(String[] args) {

int a = 6;

int b = 9;

swap(a, b);

System.out.println("交换结束后,a变量 的值是" + a + "; b变量 的值是 " + b);

}

}

结果:

swap方法里,a的值是9; b的值是6

交换结束后,a变量 的值是6; b变量 的值是 9

从上面运行结果来看, swap()方法里 a和b的值是9、6 ,交换结束后,变量a、b的值依然是6、9 。

从这个运行结果可以看出 main()方法里的变量a和b并不是 wap()方法里的变量a和b。 swap()方法里的a和b只是main()方法里变量a和b的复制品。

实例程序的执行过程:

Java 程序总是从 main()方法开始执行, main()方法开始定义了a、b两个局部变量

在内存中的存储示意图如图一所示

图一:main()方法中定义了a、b变量存储示意图

b77e4bc5e166320907c8abd407725435.png

当程序执行 swap()方法时,系统进入 swap()方法,并将 main()方法中的变量a和b作为参数值传入swap()方法,传入swap()方法的只是a和b的副本,而不是a和b本身,进入 swap()方法后系统中产生了4个变量

在内存中的存储示意图如图二所示。

图二:main()方法中的变量作为参数值传入 swap()方法存储示意图

a5a52626e930dcf7466c3ecae570ba3b.png

在main()方法中调用swap()方法时,main()方法还未结束。因此,系统分别为main()方法和swap()方法分配两块栈区,用于保存main()方法和swap()方法的局部变量。main()方法中的a、b变量作为参数值传入swap()方法,实际上是在swap()方法栈区中重新产生了两个变量a、b,并将main()方法栈区中a、 b变量的值分别赋给swap()方法栈区中的a、b参数(就是对swap()方法的a、b形参进行了初始化)。 此时,系统存在两个a变量、两个b变量,只是存在于不同的方法栈区中而已。程序在swap()方法栈区中交换a、b两个变量的值, 实际上是对图三中灰色覆盖区域的a、b变量进行 交换,交换结束后swap()方法中输出a、b变量的值,看到a的值为9, b的值为6,此时内存中的存储示意图如图三所示:

图三:swap()方法中a、b交换之后的存储示意图

0ea1f43910df0cf9eb15553d56d47fe9.png

对比图三与图一两个示意图中main()方法栈区中a、b的值并未有任何改变,程序改变的只是 swap()方法栈区中的a、b。

这就是值传递的实质:当系统开始执行方法时,系统为形参执行初始化, 就是把实参变量的值赋给方法的形参变量,方法里操作的并不是实际的实参变量。引用类型的参数传递

前面看到的是基本类型的参数传递,Java对于引用类型的参数传递,一样釆用的是值传递方式。下面程序示范了引用类型的参数传递的效果。引用类型的参数传递实例

class DataWrap {

int a;

int b;

}

public class ReferenceTransferTest {

public static void swap(DataWrap dw) {

// 下面三行代码实现dw的a、b两个成员变量的值交换

//定义一个临时变量来保存dw对象的a成员变量的值

int tmp = dw.a;

// 把dw对象的b成员变量的值赋给a成员变量

dw.a = dw.b;

// 把临时变量tmp的值赋给dw对象的b成员变量

dw.b = tmp;

System.out.println("swap方法里,a成员变量的值是" + dw.a + "; b成员变量的值是" + dw.b);

}

public static void main(String[] args) {

DataWrap dw = new DataWrap();

dw.a = 6;

dw.b = 9;

swap(dw);

System.out.println("交换结束后,a成员变量的值是" + dw.a + "; b成员变量的值是" + dw.b);

}

}

结果:

swap方法里,a成员变量的值是9; b成员变量的值是6

交换结束后,a成员变量的值是9; b成员变量的值是6

从上面运行结果来看,在swap()方法里,a、b两个成员变量的值被交换成功。不仅如此,当swap() 方法执行结束后,main()方法里a、b两个成员变量的值也被交换了。这很容易造成一种错觉:调用swap() 方法时,传入swap()方法的就是dw对象本身,而不是它的复制品。

程序的执行过程:

程序从main()方法开始执行,main()方法开始创建了一个DataWrap对象,并定义了一个dw引用变量来指向DataWrap对象,这是一个与基本类型不同的地方。创建一个对象时,系统内存中有两个东西: 堆内存中保存了对象本身,栈内存中保存了引用该对象的引用变量。接着程序通过引用来操作DataWrap 对象,把该对象的a、b两个成员变量分别赋值为6、9。

此时系统内存中的存储示意图如图四所示。

图四:main()方法中创建了 DataWrap对象后存储示意图

9f1b30ab7be76696694387c85fea6d02.png

main()方法中开始调用swap()方法,main()方法并未结束,系统会分别为main()和swap() 开辟岀两个栈区,用于存放main()和swap()方法的局部变量。调用swap()方法时,dw变量作为实参传入swap()方法,同样釆用值传递方式:把main()方法里dw变量的值赋给swap()方法里的dw形参,从 而完成swap()方法的dw形参的初始化。值得指出的是,main()方法中的dw是一个引用(也就是一个 指针),它保存了 DataWrap对象的地址值,当把dw的值赋给swap()方法的dw形参后,即让swap()方 法的dw形参也保存这个地址值,即也会引用到堆内存中的DataWrap对象。

图五显示了 dw传入swap()后的存储示意图。

图五:main()方法中的 dw 传入 swap()方法后存储示意图

ed920617b50ec0bbba81f8985ae01663.png

这种参数传递方式是不折不扣的值传递方式,系统一样复制了dw的副本传入swap() 方法,但关键在于dw只是一个引用变量,所以系统复制了 dw变量,但并未复制DataWrap对象。当程序在swap()方法中操作dw形参时,由于dw只是一个引用变量,故实际操作的还是堆内存中的DataWrap对象。此时,不管是操作main()方法里的dw变量,还是操作swap方法里的dw参数, 其实都是操作它所引用的DataWrap对象,它们操作的是同一个对象。因此,当swap()方法中交换dw 参数所引用DataWrap对象的a、b两个成员变量的值后,可以看到main()方法中dw变量所引用DataWrap 对象的a、b两个成员变量的值也被交换了。

为了更好地证明main()方法中的dw()和swap()方法中的dw是两个变量,在swap()方法的最后一行增加如下代码:

//把dw直接赋值为null,让它不再指向任何有效地址

dw = null;

执行上面代码的结果是swap()方法中的dw变量不再指向任何有效内存,程序其他地方不做任何修改。main()方法调用了 swap()方法后,再次访问dw()变量的a、b两个成员变量,依然可以输出9、6。 可见main()方法中的dw变量没有受到任何影响。实际上,当swap()方法中增加dw = null代码后,内存中的存储示意图如图五所不。

图五:将swap()方法的 dw 赋值为 null 后存储示意图

7f7f234d792c9043aa696a4ae5b60334.png

从图五来看,把swap()方法中的dw赋值为null后,swap()方法中失去了DataWrap的引用,不可再访问堆内存中的DataWraper对象。但main()方法中的dw变量不受任何影响,依然引用DataWrap对象,所以依然可以输岀DataWrap对象的a、b成员变量的值。

可变参数

JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。

方法的可变参数的声明如下所示:

typeName... parameterName

在方法声明中,在指定参数类型后加一个省略号(...) 。

一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

可变参数实例

public class VarargsDemo {

public static void main(String args[]) {

// 调用可变参数的方法

printMax(34, 3, 3, 2, 56.5);

printMax(new double[]{1, 2, 3});

}

//定义了形参可变的方法

public static void printMax( double... numbers) {

if (numbers.length == 0) {

System.out.println("No argument passed");

return;

}

//numbers被当成数组处理

double result = numbers[0];

for (int i = 1; i < numbers.length; i++){

if (numbers[i] > result) {

result = numbers[i];

}

}

System.out.println("The max value is " + result);

}

}

结果:

The max value is 56.5

The max value is 3.0

递归方法

一个方法体内调用它自身 被称为方法递归 方法递归包含了某种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。

例如有如下数学题 己知有 个数列:

062fc6150242f23e5f9c2247f38b5ede.png

其中n是大于大于0的整数,求f(10)的值。这个题可以使用递归来求得。下面程序将定义一个fn方法,用于计算f(10) 的值。

public class Recursive {

public static int fn(int n) {

if (n == 0) {

return 1;

} else if (n == 1) {

return 4;

} else {

// 方法中调用它自身 就是方法递归

return 2 * fn(n - 1) + fn(n - 2);

}

}

public static void main(String[] args) {

// 输出 fn (10) 的结果

System.out.println(fn(10));

}

}

方法的重载

Java允许同一个类里定义多个同名方法,只要形参列表不同就行。如果同一个类中包含了两个或两 个以上方法的方法名相同,但形参列表不同,则被称为方法重载。

从上面介绍可以看岀,在Java程序中确定一个方法需要三个要素。

调用者,也就是方法的所属者,既可以是类,也可以是对象。

方法名,方法的标识。

形参列表,当调用方法时,系统将会根据传入的实参列表匹配。

方法重载的要求就是两同一不同:同一个类中、方法名相同,参数列表不同。至于方法的其他部分, 如方法返回值类型、修饰符等,与方法重载没有任何关系。

public class OverLoad {

//下面定义了两个test()方法,但方法的形参列表不同

//系统可以区分这两个方法,这被称为方法重载

public void test() {

System.out.println("无参数");

}

public void test(String msg) {

System.out.println("重载的 test 方法 " + msg);

}

public static void main(String[] args) {

OverLoad ol = new OverLoad();

//调用testO时没有传入参数,因此系统调用上面没有参数的testO方法

ol.test();

//调用testO时传入了一个字符串参数

//因此系统调用上面带一个字符串参数的testO方法

ol.test("hello");

}

}

Java 允许重载任何方法, 而不只是构造器方法。因此,要完整地描述一个方法,需要指出方法名以及参数类型。这叫做方法的签名(signature)。

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java代码review是为了确保代码的质量和可维护性,以及遵循最佳实践和编码规范。以下是一些常见的Java代码review检查项: 1. 命名规范:检查变量、方法和类的命名是否符合驼峰命名法,并且能够描述其含义。 2. 代码注释:检查代码中是否有足够的注释,以解释代码的功能和实现。注释应该清晰、简洁,并且保持同步更新。 3. 代码格式化:检查代码的格式是否一致,例如缩进、空格和换行符的使用。 4. 异常处理:检查是否对可能出现的异常情况做了处理,例如使用try-catch语句来捕获异常,并给出适当的错误处理和日志记录。 5. 可读性:检查代码的可读性,确保代码清晰易懂。通过使用有意义的变量名、避免过长的方法和类,以及使用合适的代码结构来提高代码的可读性。 6. 避免硬编码:检查是否避免了硬编码,即在代码中直接使用固定的数值和字符串,应该使用常量或配置文件来管理这些值。 7. 安全性:检查是否对潜在的安全漏洞进行了预防和处理。例如,是否对用户输入进行了验证和过滤,并避免了SQL注入和跨站脚本攻击等。 8. 性能优化:检查是否有可能的性能优化点,例如避免重复计算和循环、选择合适的数据结构和算法等。 9. 代码复用:检查是否有可能的代码复用机会,例如使用继承、接口和设计模式来避免重复编写相似的代码。 10. 版本控制和代码管理:检查是否遵循正确的代码版本控制和管理,例如对代码进行适当的分支、提交和合并。 通过进行代码review,可以帮助发现并修复潜在的问题,提高代码质量和可维护性,并且促进团队之间的合作和知识共享。 ### 回答2: Java代码review是检查Java程序的代码质量和规范的过程。在进行Java代码review时,我们需要关注以下几个主要的检查项: 1. 代码风格:检查代码的缩进、命名规范、注释等,保证代码易读易懂,符合统一的编码风格。 2. 代码结构:检查代码的模块划分和类的组织结构是否合理,遵循面向对象的设计原则,并且模块之间的依赖关系是否清晰。 3. 可读性:检查代码的逻辑是否清晰,每个方法或函数是否只做一件事,避免过长的方法和复杂的嵌套结构。 4. 异常处理:检查代码中是否捕获和处理了可能出现的异常,避免程序崩溃或者出现不必要的错误。 5. 性能优化:检查代码是否存在性能问题,例如是否存在冗余的计算、不必要的内存占用等,优化代码性能提高程序运行效率。 6. 安全性:检查代码是否存在潜在的安全隐患,例如SQL注入、跨站脚本攻击等,增加代码的安全性。 7. 代码复用性:检查代码是否存在重复代码,避免代码冗余,提高代码复用性和维护性。 8. 单元测试:检查是否存在有效的单元测试覆盖率,保证代码的功能和逻辑正确性。 以上是常见的Java代码review检查项,通过对这些检查项的审核,可以帮助我们提高代码的质量、可维护性和安全性。 ### 回答3: Java代码review是一种对Java程序代码进行审查和评估的过程,旨在发现潜在的问题和改进程序质量。在进行Java代码review时需要关注以下几个检查项: 1. 代码风格:检查代码是否符合约定的编码规范和风格,比如变量命名、缩进、注释等。遵循一致的代码风格可以提高代码的可读性和维护性。 2. 逻辑错误和bug:检查代码中是否存在逻辑错误和潜在的bug,例如条件判断是否正确、循环是否正确终止等。通过预先发现这些错误可以提高程序的可靠性和稳定性。 3. 性能问题:检查代码中是否存在性能瓶颈和低效的操作,比如循环嵌套过多、频繁的对象创建和销毁等。优化这些性能问题可以提高程序的执行效率。 4. 可维护性:检查代码是否易于维护和扩展,例如代码的模块化程度、接口设计是否合理等。具有良好的可维护性可以减少代码维护的难度和成本。 5. 安全性问题:检查代码是否存在安全漏洞和潜在的攻击风险,例如未经验证的输入、SQL注入、跨站脚本攻击等。确保代码的安全性可以保护用户的信息和系统的稳定性。 6. 单元测试覆盖率:检查代码是否具有足够的单元测试覆盖率,确保代码功能的正确性和稳定性。通过编写全面的单元测试可以提高代码的可靠性和可测试性。 7. 文档和注释:检查代码是否有清晰的文档和注释,包括方法和类的功能、输入输出等。良好的文档和注释可以提高代码的可读性和理解性。 通过进行Java代码review,可以发现和纠正代码中的问题,提高代码质量和可靠性,同时也可以加强团队之间的沟通和知识交流。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值