可变参数
定义
- JDK1.5以后,定义一个方法时,如果形参个数不确定,则可以使用可变参数
要求
- 一个方法只能有一个可变参数
- 可变参数必须是形参列表的最后一个
- 实际上编译成class文件时会先封装成一个数组,再进行传递
可变参数练习
求1-n个整数中的最大值
public class ChangeArgs_Exer1 {
public static void main(String[] args) {
Count c = new Count();
System.out.println(c.max(1));
System.out.println(c.max(5,3,2,6));
}
}
class Count{
public int max(int num, int... others){
int max = num;
for (int i = 0; i < others.length; i++) {
if(max < others[i]){
max = num;
}
}
return max;
}
}
字符串拼接
public class ChangeArgs_Exer4 {
public static void main(String[] args) {
StringUtil su = new StringUtil();
System.out.println(su.concat('+'));
System.out.println(su.concat('+',"hello","world"));
}
}
class StringUtil{
public String concat(char seperator, String... args){
String str = "";
for (int i = 0; i < args.length; i++) {
if(i==0){
str += args[i];
}else{
str += seperator + args[i];
}
}
return str;
}
}
方法重载
定义
- 在同一个类中,允许存在一个以上的同名方法,数据类型不同或者数据类型个数不同或者数据类型顺序不同,与修饰符和返回值类型无关
- JVM通过方法的参数列表,调用不同的方法
方法重载练习
求各种最大值
//求两个整数的最大值
public int max(int a,int b){
return a>b?a:b;
}
//求三个整数的最大值
public int max(int a, int b, int c){
return max(max(a,b),c);
}
//求两个小数的最大值
public double max(double a, double b){
return a>b?a:b;
}
判断是否是合理的重载
//判断如下两个方法是否构成重载:是
class StringUtil{
public String concat(char seperator, String... args){
String str = "";
for (int i = 0; i < args.length; i++) {
if(i==0){
str += args[i];
}else{
str += seperator + args[i];
}
}
return str;
}
public String concat(String[] args){
String str = "";
for (int i = 0; i < args.length; i++) {
str += args[i];
}
return str;
}
}
//判断如下两个方法是否构成重载:不是
class Count{
public int getSum(int... nums){
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
public int getSum(int[] nums){
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
}
class Test06_Overload_Problem2{
public static void main(String[] args){
Count c = new Count();
System.out.println(c.sum(1,2));//(int a, int b)
System.out.println(c.sum(1,2,3));//(int... args)和(int a, int... args)都兼容,就有问题了
}
}
//Count类编译没问题,但是调用者有问题
class Count{
public int sum(int a, int b){
return a+b;
}
public int sum(int... args){
int sum = 0;
for(int i=0; i<args.length; i++){
sum += args[i];
}
return sum;
}
public int sum(int a, int... args){
int sum = a;
for(int i=0; i<args.length; i++){
sum += args[i];
}
return sum;
}
}
方法的参数传递机制
实参给形参赋值
- 形参是基本数据类型时,形参值的改变不会影响实参
- 方法的形参是引用数据类型是,形参地址值的改变不会影响实参,但形参地址值里面数据的改变会影响实参
示例1
class Test{
public static void swap(int a, int b){
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args){
int x = 1;
int y = 2;
swap(x,y);//调用完之后,x与y的值不变
}
}
示例2
class Test{
public static void change(MyData my){
my.num *= 2;
}
public static void main(String[] args){
MyData m = new MyData();
m.num = 1;
change(m);//调用完之后,m对象的num属性值就变为2
}
}
class MyData{
int num;
}
示例3
class Test{
public static void change(MyData my){
my = new MyData();//形参指向了新对象
my.num *= 2;
}
public static void main(String[] args){
MyData m = new MyData();
m.num = 1;
change(m);//调用完之后,m对象的num属性值仍然为1
}
}
class MyData{
int num;
}
示例4
public class Test {
public static void main(String[] args) {
StringUtil util = new StringUtil();
String str = "世界";
util.change(str);
System.out.println(str); //世界
}
}
class StringUtil{
public void change(String str){
str += "你好";//String对象不可变,一旦修改就会产生新对象
}
}
命令行参数
定义
- 通过命令行给main方法的形参传递的实参称为命令行参数
示例
public class TestCommandParam{
//形参:String[] args
public static void main(String[] args){
System.out.println(args);
System.out.println(args.length);
for(int i=0; i<args.length; i++){
System.out.println("第" + (i+1) + "个参数的值是:" + args[i]);
}
}
}
java TestCommandParam 1 2 3
java TestCommandParam hello world
递归
求斐波拉契数列
public class RecursionMethod3{
public static void main(String[] args) {
Count c = new Count();
System.out.println("f(10):" + c.f(10));
System.out.println("f方法被调用的总次数:" + c.total);
}
}
class Count{
int total = 0;
public int f(int n){
total++;
if(n <= 1){
return 1;
}else{
return f(n-2) + f(n-1);
}
}
}
对象数组
对象数组的内存图分析
创建学生类并排序
class Test18_ObjectArrayExer2_2{
public static void main(String[] args){
//创建一个可以装3个学生对象的数组
Student[] arr = new Student[3];//只是申明这个数组,可以用来装3个学生,此时里面没有学生对象
//从键盘输入
java.util.Scanner input = new java.util.Scanner(System.in);
for(int i=0;i<arr.length; i++){
System.out.println("请输入第" + (i+1) + "个学生信息:");
arr[i] = new Student();
System.out.print("姓名:");
arr[i].name = input.next();
System.out.print("成绩:");
arr[i].score = input.nextInt();
}
//先显示一下目前的顺序
for(int i=0; i<arr.length; i++){
System.out.println(arr[i].getInfo());
}
System.out.println("------------------------------------------");
//冒泡排序
for(int i=1; i<arr.length; i++){
for(int j=0; j<arr.length-i; j++){
//arr[j] > arr[j+1]//错误的
if(arr[j].score > arr[j+1].score){
//交换两个元素,这里是两个学生对象,所以temp也得是Student类型
Student temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//再显示一下目前的顺序
for(int i=0; i<arr.length; i++){
System.out.println(arr[i].getInfo());
}
}
}
class Student{
String name;
int score;//使用int或double都可以
public String getInfo(){
return "姓名:" + name +",成绩:" + score;
}
}