命令行参数
package com.atguigu.method;
1、命令行参数:它是指给main方法传递的参数,叫做命令行参数
2、如何给main方法的形参(String[] args)传值
(1)命令行中
java 类名 参数1 参数2 参数3 ...
(2)IDEA中
Run菜单->Edit Configurations-->
A:Main Class:main所在的类是哪个,确定是对的
B:program arguments:参数值之间使用空格分隔
public static void main(String[] args)
按理来说写成下面这种更符合:
public static void main(String... args)
但是因为可变的语法是从JDK1.5之后引入的,main是从JDK1.0就有的。
public class TestCommandParam {
public static void main(String[] args) {
System.out.println("args的长度:" + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("第" + (i+1) +"个参数是:" + args[i]);
}
}
}
方法的参数传递机制(day0117-05)
package com.atguigu.method;
方法的实参负责给形参赋值:
(1)形参是基本数据类型,那么实参给形参的是数据值,而且是数据值的“副本”。
形参的修改,如果没有返回,和实参无关,即形参的修改不会影响实参。
(2)形参是引用数据类型(数组、类等),那么实参给形参的是地址值,而且是地址值的“副本”
形参和实参其实现在指向的是同一个“对象”,
形参修改了对象的属性或者数组对象的元素,那么相当于实参对象自己修改的。
但是,如果此时形参指向了新对象/数组,就和实参对象无关了。
public class TestPassValue {
public static void main(String[] args) {
TestPassValue t = new TestPassValue();
int x = 1;
System.out.println("调用change方法之前: x = " +x);//1
t.change(x);//实参是x,x把1复制给形参a
System.out.println("调用change方法之后: x = " +x);//1
System.out.println("--------------------");
int[] arr = {1,2,3,4,5};
System.out.println("调用changeArr之前:");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
t.changeArr(arr);
System.out.println("调用changeArr之后:");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
System.out.println("------------------------");
MyData data = new MyData();
data.num = 1;
System.out.println("调用changeNum方法之前,data.num = " + data.num);
t.changeNum(data);
System.out.println("调用changeNum方法之后,data.num = " + data.num);
System.out.println("-----------------------------------");
int[] nums = {1,2,3,4,5};
System.out.println("调用grow之前nums数组:");
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
t.grow(nums);
System.out.println("调用grow之后nums数组:");
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
}
public void grow(int[] arr){
arr = new int[arr.length*2];
for (int i = 0; i < arr.length; i++) {
arr[i] = 100;
}
}
public void change(int a){//形参是(int a),
a = 2;//把a修改为2 ,修改的是形参,相当于修改的是副本
}
public void changeArr(int[] arr){
for (int i = 0; i < arr.length; i++) {
arr[i] *= 2;//把元素修改为原来的2倍
}
}
public void changeNum(MyData my){
my.num = 2;
}
}
输出结果:
调用change方法之前: x = 1
调用change方法之后: x = 1
--------------------
调用changeArr之前:
1 2 3 4 5
调用changeArr之后:
2 4 6 8 10
------------------------
调用changeNum方法之前,data.num = 1
调用changeNum方法之后,data.num = 2
-----------------------------------
调用grow之前nums数组:
1 2 3 4 5
调用grow之后nums数组:
1 2 3 4 5
Process finished with exit code 0
形参是基本数据类型
案例:编写方法,交换两个整型变量的值
package com.atguigu.test05.param;
public class PrimitiveTypeParam {
void swap(int a, int b){//交换两个形参的值
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args) {
PrimitiveTypeParam tools = new PrimitiveTypeParam();
int x = 1;
int y = 2;
System.out.println("交换之前:x = " + x +",y = " + y);//1,2
tools.swap(x,y);//实参x,y是基本数据类型,给形参的是数据的“副本”,调用完之后,x与y的值不变
System.out.println("交换之后:x = " + x +",y = " + y);//1,2
}
}
形参是引用数据类型
package com.atguigu.test05.param;
public class ReferenceTypeParam {
void swap(MyData my){//形参my是引用数据类型,接收的是对象的地址值,形参my和实参data指向同一个对象
//里面交换了对象的两个实例变量的值
int temp = my.x;
my.x = my.y;
my.y = temp;
}
public static void main(String[] args) {
ReferenceTypeParam tools = new ReferenceTypeParam();
MyData data = new MyData();
data.x = 1;
data.y = 2;
System.out.println("交换之前:x = " + data.x +",y = " + data.y);//1,2
tools.swap(data);//实参是data,给形参my的是对象的地址值,调用完之后,x与y的值交换
System.out.println("交换之后:x = " + data.x +",y = " + data.y);//2,1
}
}
public class MyData{
int x;
int y;
}
形参是数组
package com.atguigu.test05.param;
public class ArrayTypeParam {
void sort(int[] arr){//给数组排序,修改了数组元素的顺序,这里对arr数组进行排序,就相当于对nums数组进行排序
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < arr.length - i; j++) {
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
void iterate(int[] arr){//输出数组的元素,元素之间使用空格分隔,元素打印完之后换行
//这个方法没有修改元素的值
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
ArrayTypeParam tools = new ArrayTypeParam();
int[] nums = {4,3,1,6,7};
System.out.println("排序之前:");
tools.iterate(nums);//实参nums把数组的首地址给形参arr,这个调用相当于输出nums数组的元素
//对数组的元素值没有影响
tools.sort(nums);//对nums数组进行排序
System.out.println("排序之后:");
tools.iterate(nums);//输出nums数组的元素
//上面的代码,从头到尾,堆中只有一个数组,没有产生新数组,无论是排序还是遍历输出都是同一个数组
}
}
输出结果:
排序之前:
4 3 1 6 7
排序之后:
1 3 4 6 7
形参指向新对象
package com.atguigu.test05.param;
public class AssignNewObjectToFormalParam {
void swap(MyData my){
my = new MyData(); //这里让my形参指向了新对象,此时堆中有两个MyData对象,和main中的data对象无关
int temp = my.x;
my.x = my.y;
my.y = temp;
}
public static void main(String[] args) {
//创建这个对象的目的是为了调用swap方法
AssignNewObjectToFormalParam tools = new AssignNewObjectToFormalParam();
MyData data = new MyData();
data.x = 1;
data.y = 2;
System.out.println("交换之前:x = " + data.x +",y = " + data.y);//1,2
tools.swap(data);//调用完之后,x与y的值交换?
System.out.println("交换之后:x = " + data.x +",y = " + data.y);//1,2
}
}
一道面试题
package com.atguigu.exer.param;
创建对象:
new 类名()
new 类名(实参列表)
如果没有把new表达式赋值给一个变量,那么这样的对象称为匿名对象。
只要是对象,就可以调用这个类的方法等
public class Tools {
public static void main(String[] args) {
int i = 0;
new Tools().change(i);//因为Tools对象只在这里用了一次,所以用匿名对象直接调用change方法了
i = i++; //(1)先取i的值,放到操作数栈中(2)i自增为1(3)把操作数栈中的0赋值给i
System.out.println("i = " + i);//i=0
}
void change(int i){//形参i是基本数据类型,所以change方法中修改i的值,和实参无关
i++;
System.out.println("change方法中i = " + i);//i=1
}
}
方法重载
package com.atguigu.method;
1、方法的重载(Overload):当一个类中出现了 方法名相同,形参列表不同的两个或多个方法,称为方法的重载。
关键词:(1)方法名相同,(2)形参列表不同
方法名:代表方法的功能,见名知意
如果多个方法,它们的功能是一样的,只是针对的数据不同,通常需要用方法的重载。
例如:
(1)定义方法求两个整数的最大值
(2)定义方法求三个整数的最大值
(3)定义方法求两个小数的最大值
(4)定义方法求n个整数最大值
分析:求最大值,方法名可以写成max,但是这些方法针对的数据不同,有两个整数,两个小数的,更多个整数的...
2、当调用重载的方法时,原则
(1)先找最匹配的
实参的个数和类型与形参的个数和类型一样的。
(2)再找能够兼容的
形参的类型可以兼容实参的类型(自动类型提升)
或
形参的个数可以兼容实参的个数(可变参数)
(3)如果最匹配的没有,兼容的也没有,就编译报错
如果匹配的多个可以兼容的方法,也会编译报错
public class TestOverload {
public static void main(String[] args) {
TestOverload t = new TestOverload();
System.out.println(t.max(4, 5));
System.out.println(t.max(4.5, 5.3));
System.out.println(t.max(4,5,6));
System.out.println(t.max(4,5,6,8,9));
System.out.println("--------------------");
System.out.println(t.max(5, 2.3));// max(double a, double b) 形参double a兼容int类型的5
System.out.println("-----------------------");
// System.out.println(t.max(1.2, 2.3, 5.6, 8.5));//编译报错
/*
个数上,只有int max (int... nums)可以接收它
但是它的类型又无法接收 double > int类型,不能兼容
*/
}
//求两个整数的最大值
int max(int a, int b){
System.out.println("TestOverload.max(int a,int b)");
return a>b?a:b;
}
//求三个整数的最大值
int max(int a, int b,int c){
/*int big = a > b ? a : b;
big = big > c ? big : c;
return big;*/
/* int big = max(a,b);
big = max(big, c);
return big;*/
System.out.println("TestOverload.max(int a,int b, int c)");
return max(max(a,b),c);
}
//求两个小数的最大值
double max(double a, double b){
System.out.println("TestOverload.max(double a, double b)");
return a > b ? a : b;
}
//求n个整数最大值
int max (int... nums){
System.out.println("TestOverload.max(int... nums)");
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
max = max(max, nums[i]);
}
return max;
/*int max = nums[0];
for (int i = 1; i < nums.length; i++) {
if(nums[i] > max){
max = nums[i];
}
}
return max;*/
}
// int max(int[] nums){//编译报错,因为此时编译器认为,int max(int[] nums)和int max (int... nums)一样的
// int max = nums[0];
// for (int i = 1; i < nums.length; i++) {
// if(nums[i] > max){
// max = nums[i];
// }
// }
// return max;
// }
/*int max(int first, int... nums){
int max = first;
for (int i = 0; i < nums.length; i++) {
if(nums[i] > max){
max = nums[i];
}
}
return max;
}*/
}
方法重载练习1、
package com.atguigu.exer.overload;
/*
(1)声明MathTools工具类,包含:
- int compare(int a, int b):
比较两个整数大小关系,如果第一个整数比第二个整数大,则返回正整数,如果第一个整数比第二个整数小,则返回负整数,如果两个整数相等则返回0;
- int compare(double a, double b):
比较两个小数大小关系,如果第一个小数比第二个小数大,则返回正整数,如果第一个小数比第二个小数小,则返回负整数,如果两个小数相等则返回0;
- int compare(char a, char b):
比较两个字符大小关系,如果第一个字符比第二个字符编码值大,则返回正整数,如果第一个字符比第二个字符编码值小,则返回负整数,如果两个字符相等则返回0;
(2)在测试类的main方法中调用
*/
public class MathTools {
int compare(int a, int b){
return a-b;
}
int compare(double a, double b){
// return a-b;//编译错误,因为a和b是double,相减的结果也是double,而方法的返回值类型要求是int
// return (int)(a-b);//编译通过,但是有问题。假设a = 5.6,b=5.2,它俩不相等,但是 (int)(a-b)结果是0,意味着相等
if(a > b){
return 1;//只要是正整数就可以,习惯上用1
}else if(a < b){
return -1;
}
return 0;
}
int compare(char a, char b){
return a-b;
}
}
2、
package com.atguigu.exer.overload;
public class ArrayTools {
void sort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < arr.length - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void sort(double[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < arr.length - i; j++) {
if (arr[j] > arr[j + 1]) {
double temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void sort(char[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < arr.length - i; j++) {
if (arr[j] > arr[j + 1]) {
char temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
String toString(int[] arr) {
String str = "[";
for (int i = 0; i < arr.length; i++) {
if (i == 0) {
str += arr[i];
} else {
str += "," + arr[i];
}
}
str += "]";
return str;
}
String toString(double[] arr) {
String str = "[";
for (int i = 0; i < arr.length; i++) {
if (i == 0) {
str += arr[i];
} else {
str += "," + arr[i];
}
}
str += "]";
return str;
}
String toString(char[] arr) {
String str = "[";
for (int i = 0; i < arr.length; i++) {
if (i == 0) {
str += arr[i];
} else {
str += "," + arr[i];
}
}
str += "]";
return str;
}
}
package com.atguigu.exer.overload;
/*
(1)声明一个数组工具类ArraysTools,包含几个重载方法
- 重载方法系列1:可以为int[],double[],char[]数组实现从小到大排序
- void sort(int[] arr)
- void sort(double[] arr)
- void sort(char[] arr)
- 重载方法系列2:toString方法,可以遍历int[],double[],char[]数组,遍历结果形式:[元素1,元素2,。。。]
- String toString(int[] arr)
- String toString(double[] arr)
- String toString(char[] arr)
(2)在测试类的main方法中调用
Java中,double类型的变量,可以接收int类型的值,但是double[]数组,不能接收int[]的数组
*/
public class ArrayToolsTest {
/*public static void main(String[] args) {
int num = 1;
double d = num;
int[] arr1 = {1,2,3,4,5};
double[] arr2 = arr1;//错误
}*/
public static void main(String[] args) {
int[] arr1 = {2,4,6,1,2};
ArrayTools tools = new ArrayTools();
System.out.println("排序前:" + tools.toString(arr1));
tools.sort(arr1);
System.out.println("排序后:" + tools.toString(arr1));
System.out.println("---------------------------");
double[] arr2 = {5.2,3.2,4.2,1.2};
System.out.println("排序前:" + tools.toString(arr2));
tools.sort(arr2);
System.out.println("排序后:" + tools.toString(arr2));
System.out.println("------------------------");
char[] arr3 = {'f','d','a','c','z'};
System.out.println("排序前:" + tools.toString(arr3));
tools.sort(arr3);
System.out.println("排序后:" + tools.toString(arr3));
}
}
排序前:[2,4,6,1,2]
排序后:[1,2,2,4,6]
---------------------------
排序前:[5.2,3.2,4.2,1.2]
排序后:[1.2,3.2,4.2,5.2]
------------------------
排序前:[f,d,a,c,z]
排序后:[a,c,d,f,z]
Process finished with exit code 0
对象数组
package com.atguigu.array;
public class Circle {
double radius;
double area(){
return Math.PI * radius * radius;
}
double perimeter(){
return 2 * Math.PI * radius;
}
String getInfo(){
return "半径:" + radius +
",面积:" + area()
+",周长:" +perimeter();
}
}
package com.atguigu.array;
我们之前第4章学习了数组,元素都是int等基本数据类型的数组。
现在要讲的是对象数组,元素是引用数据类型。
演示:存储5个圆对象到数组中。
写代码先有类,再有对象。
数组的元素如果是引用数据类型,默认值是null。
对象数组中元素存储的是对象的首地址。
public class TestObjectArray {
public static void main(String[] args) {
//创建5个圆对象,半径是随机产生, [1,10)之间
//(1)先声明和创建数组,长度为5
//元素的类型:Circle
//一维数组的声明和动态初始化的公式
//元素的数据类型[] 数组名 = new 元素的数据类型[长度];
Circle[] arr = new Circle[5];
//(2)为元素赋值
//元素类型是Circle,那么必须赋值为Circle的对象
for (int i = 0; i < arr.length; i++) {
arr[i] = new Circle();
/*
Math.random() => [0,1)
Math.random()*9 => [0,9)
Math.random()*9+1 => [1,10)
*/
arr[i].radius = Math.random() * 10 + 1;
System.out.println(arr[i].getInfo());
//因为arr[i]是Circle类型的对象,就可以调用就Circle类中声明的属性和方法
}
}
}
小练习
(1)定义学生类Student
- 声明姓名和成绩实例变量,
- String getInfo()方法:用于返回学生对象的信息
(2)测试类的main中创建一个可以装3个学生对象的数组,从键盘输入3个学生对象的信息,并且按照学生成绩排序,显示学生信息
package com.atguigu.exer.array;
/*
(1)定义学生类Student
- 声明姓名和成绩实例变量,
- String getInfo()方法:用于返回学生对象的信息
*/
public class Student {
String name;
int score;
String getInfo(){
return "姓名:" + name +",成绩:" + score;
}
}
package com.atguigu.exer.array;
import java.util.Scanner;
public class TestStudentArray {
public static void main(String[] args) {
//创建一个可以装3个学生对象的数组
Student[] arr = new Student[3];
Scanner input = new Scanner(System.in);
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第" + (i+1) +"个学生的信息:");
/*System.out.print("姓名:");
String name = input.next();
System.out.print("成绩:");
int score = input.nextInt();
Student student = new Student();
student.name = name;
student.score = score;
arr[i] = student;*/
arr[i] = new Student();
System.out.print("姓名:");
arr[i].name = input.next();
System.out.print("成绩:");
arr[i].score = input.nextInt();
}
//统一显示
System.out.println("所有的学生信息如下:");
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++){
if(arr[j].score > arr[j+1].score){//按照两个学生对象的成绩比较
//交换两个成绩是错误
/*int temp = arr[j].score;
arr[j].score = arr[j+1].score;
arr[j+1].score = temp;*/
//交换两个学生对象
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());
}
input.close();
}
}