0.类的结构之二:方法
1.方法的声明及使用
1.1 方法声明的格式说明
测试类中方法的定义
*
* 0. 举例:
* Scanner类中:nextXxx():nextInt()
* Math类中:random() / sqrt()
* Arrays类中:equals() / toString() / sort(int[] arr) / binarySearch()
* * 1. 方法的定义(或声明)格式:
* 权限修饰符 返回值类型 方法名(形参列表){
* //方法体
* }
* * 2. 定义的细节:
* ① 权限修饰符:修饰方法可以使用的权限修饰符有:public 、 protected 、缺省 、 private
* ② 返回值类型:如果一个方法调用完以后,需要有相关数据的返回。那么我们就可以指定要返回的数据的类型。
* 方法可以分为:一类是有返回值的(需要指明返回值的类型。并且方法内需要使用return + 具体类型的变量或常量)
* 一类是没有返回值的(使用void表示返回值类型即可)。
* * 开发中定义方法的话,到底要不要定义返回值类型呢?
* > 根据题目要求
* > 具体问题具体分析
* ③ 方法名:方法名是一个标识符,需要满足标识符定义的规则、规范。 “见名知意”
* ④ 形参列表:在形参的位置可以定义一个或多个变量。
* 格式:声明时,只需要指明形参的类型和形参名即可。在调用方法时,给形参赋值。(数据类型 变量1,数据类型 变量2,...)
* 赋值:形参在方法被调用时,赋值。赋的值,通常称为实参。
* * 开发中定义方法的话,到底要不要定义形参列表呢?
* > 根据题目要求
* > 具体问题具体分析
* ⑤ 方法体:声明在方法结构的一对{}内。当方法被调用时,真正执行的逻辑。
1.2 方法内的使用说明
① 方法内可以调用当前类的属性。执行方法时,属性的值即为调用当前方法的对象的属性值。
② 方法内可以调用当前类的(其他)方法。方法内不能定义方法。
2.关键字return的使用
如果一个方法声明时,有返回值类型(即:返回值类型位置不是void),则方法内部一定要使用return结构。
格式 : return + 变量/常量。
return 的作用: ① 结束方法:在方法体内,一旦执行了return,则跳出当前方法。
② 结束方法的同时,可以返回一个变量或常量给方法的调用者。
注意点:
①return后面不能再声明执行语句。
②区分return和break的作用。
- 代码示例
class User{
//1. 属性
String name;//名字
int age;//年龄
//2. 方法
public void eat(){
System.out.println("用户吃饭");
//eat();
// walk();
// System.out.println(show());
}
public void walk(){
System.out.println("用户走路");
}
public String show(){
return "name = " + name + ", age = " + age; //方法内可以调用当前类的属性
// return 123;
}
public void sleep(int hour){
System.out.println("每天睡眠" + hour + "个小时");
}
public double getAge(){
// return age;
return 1;
}
public void info(){
if(age >= 18){
System.out.println("成人了");
return; //用于表示方法的结束
}else{
System.out.println("未成年");
}
System.out.println("执行结束");
}
}
- 测试类
public class UserTest {
public static void main(String[] args) {
// Scanner scan = new Scanner(System.in);
// int num = scan.nextInt();
User u1 = new User();
u1.name = "Tom";
u1.age = 10;
String info = u1.show();
System.out.println(info);
User u2 = new User();
u2.name = "Jerry";
System.out.println(u2.show());
u1.eat();
}
}
3.对象数组
-如果数组中的元素是类的对象,则称为对象数组。
比如:String[] \ Student[] \ Person[]
- 练习
-定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
问题一:打印出3年级(state值为3)的学生信息。
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
-提示:
1) 生成随机数:Math.random(),返回值类型double;
2) 四舍五入取整:Math.round(double d),返回值类型long。
代码实现
/**
* 4. 对象数组题目:
* 定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。
*/
public class Student {
int number;//学号
int state;//年级
int score;//成绩
}
public class StudentTest {
public static void main(String[] args) {
//数组是引用数据类型,数组的元素可以是基本数据类型,也可以是引用数据类型:
//String[] arr = new String[10]
//int[][] arr1 = new int[10][];
//Student[] arr2 = new Student[10];
//创建对象数组
Student[] stus = new Student[20];
for(int i = 0;i < stus.length;i++){
//给数组元素赋值
stus[i] = new Student();
//给数组元素(对象)的属性赋值
stus[i].number = i + 1;
stus[i].state = (int)(Math.random() * 6 + 1);
stus[i].score = (int)(Math.random() * 101);
}
//问题一:打印出3年级(state值为3)的学生信息。
for(int i = 0;i <stus.length;i++){
if(3 == stus[i].state){
Student s = stus[i];
System.out.println("学生信息为:number = " + s.number + ", state = " + s.state + ", score = " + s.score);
}
}
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
//排序前:
System.out.println("排序前:");
for(int i = 0;i <stus.length;i++){
Student s = stus[i];
System.out.println("学生信息为:number = " + s.number + ", state = " + s.state + ", score = " + s.score);
}
//冒泡排序
for(int i = 0;i < stus.length - 1;i++){
for(int j = 0;j < stus.length - 1 -i;j++){
if(stus[j].score > stus[j + 1].score){
//错误的!
// int score = stus[j].score;
// stus[j].score = stus[j + 1].score;
// stus[j + 1].score = score;
//正确的:
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
//排序后:
System.out.println("排序后:");
for(int i = 0;i <stus.length;i++){
Student s = stus[i];
System.out.println("学生信息为:number = " + s.number + ", state = " + s.state + ", score = " + s.score);
}
}
}
代码实现的升级
- Student
public class Student {
int number;//学号
int state;//年级
int score;//成绩
public String getInfo(){
return "学生信息为:number = " + number + ", state = " + state + ", score = " + score;
}
}
- StudentUtil
public class StudentUtil {
/**
* 打印出指定年级的学生信息
* @param stus 指定的学生数组
* @param state 指定的年级
*/
public void printStudentWithState(Student[] stus,int state){
for(int i = 0;i <stus.length;i++){
if(state == stus[i].state){
Student s = stus[i];
System.out.println(s.getInfo());
}
}
}
/**
* 遍历指定的学生数组中的学生信息
* @param stus
*/
public void printStudent(Student[] stus){
for(int i = 0;i <stus.length;i++){
Student s = stus[i];
System.out.println(s.getInfo());
}
}
/**
* 对学生数组进行排序
*/
public void sortStudents(Student[] stus,String sort){
if("ascend".equals(sort)){ //ascend:升序
for(int i = 0;i < stus.length - 1;i++){
for(int j = 0;j < stus.length - 1 -i;j++){
if(stus[j].score > stus[j + 1].score){
//正确的:
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
}else if("descend".equals(sort)){ //descend:降序
for(int i = 0;i < stus.length - 1;i++){
for(int j = 0;j < stus.length - 1 -i;j++){
if(stus[j].score < stus[j + 1].score){
//正确的:
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
}else{
System.out.println("指定的排序方式有误!");
}
}
}
- StudentTest
public class StudentTest { //测试类
public static void main(String[] args) {
//创建对象数组
Student[] stus = new Student[20];
for(int i = 0;i < stus.length;i++){
//给数组元素赋值
stus[i] = new Student();
//给数组元素(对象)的属性赋值
stus[i].number = i + 1;
stus[i].state = (int)(Math.random() * 6 + 1);
stus[i].score = (int)(Math.random() * 101);
}
//问题一:打印出3年级(state值为3)的学生信息。
StudentUtil util = new StudentUtil();
util.printStudentWithState(stus,3);
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
//排序前:
System.out.println("排序前:");
util.printStudent(stus);
//冒泡排序
util.sortStudents(stus,"descend");
//排序后:
System.out.println("排序后:");
util.printStudent(stus);
}
}
4.匿名对象
匿名对象: 创建的对象没有声明一个具体的变量名。
通常匿名对象只能使用一次。
- 代码演示
UserTest test = new UserTest();
User u3 = new User();
u3.name = "Tonny";
test.showUser(u3);
System.out.println(u3);
//匿名对象
new User().name = "Kitty";//对象1
new User().age = 10;//对象2
test.showUser(new User());//通常见到的匿名对象的使用场景
5.方法的重载
方法的重载概念
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
总结:“两同一不同”:同一个类、相同的方法名;参数列表不同(参数个数不同或参数类型不同)
构成重载的举例:
举例一:
//Arrays类中的sort()\binarySearch()\equals()
//PrintStream类中的println()
举例二:
//如下的个方法构成重载
public void getSum(int i,int j){
System.out.println(i + j);
}
public void getSum(double d1,double d2){
System.out.println(d1 + d2);
}
public void getSum(double d1,double d2,double d3){
System.out.println(d1 + d2 + d3);
}
不构成重载的举例:
// 与上述的三个方法不构成重载
public void getSum(double do1,double do2){
System.out.println(do1 * do2);
}
public int getSum(double do1,double do2){
return (int)(do1 + do2);
}
如何判断是否构成方法的重载?
只要多个方法满足"两同一不同",则称这些方法彼此之间构成重载。
强调:方法的重载与权限修饰符、返回值类型、形参名、方法体都没关系
如何确定类中某一个方法的调用:
① 对象只能调用所属类中声明的方法
② 通过方法名区分
③ 通过方法的形参列表区分
注意:在定义类时,如果类中的某些方法方法名相同,形参列表也相同。则这些方法会编译报错。
原因:编译器会认为这些方法是相同的方法,而 java程序是不允许定义相同方法。
6.可变个数形参的方法
- jdk 5.0 新增的特性:可变个数形参的方法
- 可变个数形参的格式为:数据类型 … 变量名
- 可变个数形参的方法在调用时,可以给可变个数形参赋值的变量个数为:0个,1个,2个,…
- 可变个数形参的方法与本类中其他的同名方法构成重载。特别的情况见5
- 可变个数形参的方法与本类中使用数组定义的形参的方法不构成重载,且在类中不能同时声明。
- 可变个数形参声明在方法中的话,必须声明为最后一个形参。
- 一个方法中最多声明一个可变形参
- 举例
public class ArgsTest {
public static void main(String[] args) {
ArgsTest test = new ArgsTest();
test.show(123);
test.show(new int[]{123,234});
test.show(123,234);
test.show();
}
//如下的4个方法构成重载
public void show(int i){
System.out.println("11111");
}
public void show(double d){
System.out.println("22222");
}
public void show(String s,int i){
System.out.println("33333");
}
//String sql = "select id,name,email,salary from users where name = ? and salary > ?";
public void show(int ... args){
System.out.println("44444");
for(int i = 0;i < args.length;i++){
System.out.println(args[i]);
}
}
public void show(String s,int ... args){
}
// public void show(int[] args){
// for(int i = 0;i < args.length;i++){
// System.out.println(args[i]);
// }
// }
}