1. 可变参数
对数组的参数做的简化操作(在调用处有简化)
语法:数据类型...变量名
注意:
a. 可变参数就当做数组去使用就可以
b. 一个方法中可变参数必须是参数列表的最后一个
c. 可变参数的实参都必须符合(相同)数据类型
练习:
1. n个数int值中找最大值
2. n个字符串拼接(无缝拼接) javabigdatamysql
3. n个字符串拼接(有间隔符拼接) java+bigdata+mysql
2. 方法的重载 ★
最终的好处:解决我们相同类型方法,起方法名的问题!
方法的要求:在同一个类中,不允许出现两个完全相同的方法
要求:
a. 同一个类中,方法名可以相同
b. 但是形参列表必须不同(个数、顺序->类型、类型)任何一个不同就可以
c. 和返回值无关
d. 和访问修饰符无关(还没讲)
重载方法调用的时候,先找完全符合的,找不到完全符合的,找兼容的!
如果有多个兼容的就报错!
同类型的数组和可变参数是相同的东西
3. 参数的传递机制
形参:在方法定义位置,指定的形式参数
实参:在调用方法时,需要指定实际的参数
参数的传递机制:实参赋给形参的过程
4. 命令行参数(了解)
5. 递归(需要方法的知识)
属于循环的一种?
5.1 直接递归 ★
方法自己调用自己
5.2 间接递归
A->B->C->A
java.lang.StackOverflowError 内存溢出的错误
递归一定要有出口!
需求:打印3次好好学习,天天向上!并且将该需求的内存图画出!
出现宕机:
① 优化代码
② 加机器
6. 对象数组
对象数组的技术要求和普通数组都是一样!
int[] arrs=new int[5];//基本数据类型的数据
String[] strs=new String[5];//引用数据类型的数组
Person[] pers=new Person[5];//引用数据(自定义的)类型的数组
对象数组的默认值是null
该数组的元素,存储的是Person对象(Person对象的地址)
练习:
1. 手动输入五位同学的姓名和java成绩,输入的时候,将这些数据存储起来
输入完毕后,将所有信息展示(张三--90)
7. 封装
面向对象三大特性:封装、继承、多态
“封装”字面意思:快递打包...
封装的好处:安全、保护隐私
7.1 对属性的封装:
① 对需要封装的属性设置访问权限(私有的)
② 对外提供两个方法(对age的操作->设置、获取)
7.2 权限(访问)修饰符
设置元素(类、成员变量、成员方法)的访问范围的!
名称 本类内 本包内 其他包
public 公有的 √ √ √
缺省的 缺省的 √ √ ×
protected 受保护的 (讲完继承再讲)
private 私有的 √ × ×
类的权限修饰符,只能是public或者缺省的(什么也不写)
成员变量(属性)、成员方法、构造器、成员内部类,这个四个修饰符都可以修饰
练习:
1. 创建一个Employee类,具有属性(id,age,name,salary),对所有属性进行私有化
每个属性都提供对应的get/set方法,并且提供setAll和getInfo!
创建其3个对象,存放在对象数组中,循环遍历其个人信息!
示例:1. 可变参数
public int sums(int a, int...abc){//要求最少有一个int值参数
//abc还是当做一个数组去使用
int sum=a;
for (int i = 0; i < abc.length; i++) {
sum+=abc[i];
}
return sum;
}
示例:2. 方法的重载
public class MyUtils {
public double he(int a,double b){
System.out.println("int+double");
return a+b;
}
public double he(double a,int b){
System.out.println("double+int");
return a+b;
}
}
main方法中调用:
public class Demo2 {
public static void main(String[] args) {
MyUtils myUtils=new MyUtils();
//myUtils.he(3,4);//一个double一个int 优先级一样,则报错(就近原则) 【编译错误: 对he的引用不明确】
myUtils.he(3,4.5);//可以
}
}
示例:2. 方法的重载
public class MyUtils {
public int he(int[] arrs){
System.out.println("数组");
int sum=0;
for (int i = 0; i < arrs.length; i++) {
sum+=arrs[i];
}
return sum;
}
/* 这样不行,和上面的方法算同一个方法名
public int he(int...arrs){
return 0;
} */
public int he(int a,int...arrs){//arrs就是个数组
return 0;
}
}
示例:3. 参数的传递机制【下面灰色的输出代码完全一样】
public class TestDemo3 {
public void method(int[] arrs,int a){
arrs[1]=10;
a=20;
//查看结果
for (int i = 0; i < arrs.length; i++) {
System.out.print(arrs[i]);
}
System.out.println(a);
}
}
main方法中调用:
public class Demo3 {
public static void main(String[] args) {
TestDemo3 testDemo3=new TestDemo3();
int[] arrs={2,3,4,5};
int a=5;
testDemo3.method(arrs,a);
System.out.println("-----------------");
//查看结果
for (int i = 0; i < arrs.length; i++) {
System.out.print(arrs[i]);
}
System.out.println(a);
}
}
输出:
2104520
-----------------
210455
画内存图验证
引用数据类型,栈内存存储的是地址,在方法传参的时候,就是地址传递(引用)-->多个变量指向同一个空间(堆内存、常量池)
基本数据类型,栈内存中存储的是值,在方法传参的时候,就是值传递
示例:3. 参数的传递机制【3个java类文件】
public class Person {
int id;
int age;
}
public class TestDemo3 {
public void method(Person person,char c){
//person=new Person();//加了一行代码
person.age=18;
c='a';
System.out.println(person.id+"-"+person.age+"-"+c);//0-18-a
}
}
main方法中调用:
public class Demo3 {
public static void main(String[] args) {
Person person=new Person();
person.id=10;
person.age=20;
char c='b';
TestDemo3 testDemo3=new TestDemo3();
testDemo3.method(person,c);
System.out.println(person.id+"-"+person.age+"-"+c);
}
}
输出:
10-18-a
10-18-b
Person类是引用类型,所以原理跟上上面数组示例一样。
如果把“TestDemo3”类中的这一行前面的注释去掉:
person=new Person();//加了一行代码
则输出:
0-18-a
10-20-b
因为:“Java【05】数组”中画内存图时,有总结:只要见到new关键字,肯定会在堆内存开空间
具体地画一下内存图。
【传入参数后,有重新new 的区别】
示例:4. 命令行参数(了解)
public class Demo4 {
//主方法 无返回值,但是有参数(String[])
//命令行参数就是为main方法的args数组赋值的!
public static void main(String[] args) {
System.out.println(args.length);
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
D:\javademo\day09_pm>javac Demo4.java
D:\javademo\day09_pm>java Demo4 1 hello
2
1
hello
示例:5. 递归【5.1 直接递归】
public class TestDemo5 {
public void method(){
System.out.println("aaaaaa");
method();//自己调用自己
}
}
main方法中调用:
public class Demo5 {
public static void main(String[] args) {
TestDemo5 testDemo5=new TestDemo5();
testDemo5.method();
}
}
输出:
aaaaaa
aaaaaa
aaaaaa【一直输出……最终报错】
Exception in thread "main" java.lang.StackOverflowError
……
这种递归(只入栈,不出栈),和直接 while死循环 有点不一样。
while(true) {
System.out.println("aaaaaa");
}
递归内存溢出,这边因为只入栈,不出栈;所以,内存早晚会溢出。
递归内存图
示例:5. 递归【递归一定要有出口!】
public class TestDemo5 {
public void method(int a){
System.out.println("好好学习天天向上"+a);
if(a<2){
a++;
method(a);//满足条件就调用,不满足条件则不调用
}
}
}
main方法中调用:
public class Demo5 {
public static void main(String[] args) {
TestDemo5 testDemo5=new TestDemo5();
testDemo5.method(0);
}
}
输出:
好好学习天天向上0
好好学习天天向上1
好好学习天天向上2
示例:7.2 权限(访问)修饰符【注:类 Demo7 和 Demo7_1,都写在 Demo7.java 文件中】
public class Demo7 {
public int a;//公有的修饰符
int b;//缺省的修饰符
private int c;//私有的修饰符
public void method1(){
method3();
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
void method2(){
}
private void method3(){
}
}
class Demo7_1{//该类就是被缺省的修饰符修饰
}
main方法中调用:
public class Demo8 {
public static void main(String[] args) {
Demo7 demo7=new Demo7();//有Demo7的访问权限!
//Demo7_1 demo7_1=new Demo7_1();//有Demo7_1的访问权限!
System.out.println(demo7.a);
System.out.println(demo7.b);
//System.out.println(demo7.c);
demo7.method1();
demo7.method2();
//demo7.method3();
}
}