方法重载设计
需求:在同一个类中,分别定义两个整数、小数之和。
//求两个整数之和
static int getSum1(int x,int y){
return x + y;
}
//求两个小数之和
static double getSum2(double x,double y){
return x + y;
}
需求:在同一个类中,分别定义打印String int double boolean类型的方法。
//打印String
static void pString1(String data){
System.out.println(data);
}
//打印int
static void pString2(int data){
System.out.println(data);
}
//打印double
static void pString3(double data){
System.out.println(data);
}
......
以上设计,相同的功能在不同情况下调用不同方法名,很难分清。
**重载方法:**在同一个类中,定义多个名称相同吗,但是参数的类型或者个数不相同的方法。
方法重载的作用:屏蔽了同一功能的方法由于参数不同所造成的方法名不同。
方法重载原则:两同一不同。即同类中相同的方法名,参数列表(参数类型、参数个数、参数顺序)不同
注意:方法重载和方法的返回类型没有关系,只是一般要求返回值类型一致。参数列表和参数名称没关系,方法的重载和形参没关系。
以上两个需求改进之后如下,方法名相同,形参不同。
//求两个整数之和
static int getSum(int x,int y){
return x + y;
}
//求两个小数之和
static double getSum(double x,double y){
return x + y;
}
//打印String
static void pString(String data){
System.out.println(data);
}
//打印int
static void pString(int data){
System.out.println(data);
}
//打印double
static void pString(double data){
System.out.println(data);
}
思考:为什么System.out.pringln();可以打印任意类型的数据?
原因:查看源代码,证明多个print方法存在重载关系。
方法的递归
递归定义:指在一个方法的内部调用自身的过程,递归必须要有结束条件,否则将陷入无限递归,永远无法结束调用。
//方法的递归
class MethodDemo3
{
public static void main(String[] args)
{
int ret = fn(6);//调用fn方法
System.out.println(ret);
}
//斐波那契额数列:通项公式 F(0) = 0,F(1) = 1,Fn = F(n-1) + F(n-2)
static int fn(int n){//定义fn方法
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}else{//n不等于0或1
return fn(n - 1) + fn(n - 2);//递归:调用自身
}
}
}
JVM内存划分,人为的根据不同内存空间的存储特点以及存储的数据:
- 程序计数器: 当前线程所执行的字节码的行号指示器。
- 本地方法栈: 为虚拟机使用的native方法服务。
- Java虚拟机栈: 描述Java方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。
每一个方法,创建一个栈帧,栈帧存放了当前方法的数据信息(局部变量),当方法调用完毕该方法的栈帧就被销毁了. - Java堆: 被所有线程共享的一块内存区域,在虚拟机启动时创建。所有的对象实例以及数组都要在堆上分配使用new关键字,就表示在堆中开辟一块新的存储空间)。
- 方法区:线程共享的内存区域,存储已被虚拟机加载的类信息、常量、静态变量即时编译器编译后的代码数据等这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载)。
GC(Garbage Cllection):垃圾回收器。
Java的自动垃圾回收机制:简单理解为,
程序员就不需要再手动的去控制内存的释放。当VM发觉内存资源紧张的时候,就会自动地去清理无用对象(没有被引用到的对象)所占用的内存空间。
数组
当我们要处理一组相同类型的数据时,如:所有员工的信息。我们使用数组来解决。
数组: 按一定顺序有序排列的相同类型的数据集合。数组中每一个数据称为元素,不同元素以索引来表示其存放的位置,索引从0开始,步长为1 。
数组的定义
方式1:数据类型[ ] 变量名;如:int[ ] x;(建议使用方式1)
方式2:数据类型 变量名[ ] ;如:int x[ ];
数组必须初始化后才能使用,因为初始化表示在内存中分配空间。
//数组的定义
class ArrayDemo1
{
public static void main(String[] args)
{
//表示一个变量
int age;
//表示全班同学年龄
int[] ages1;//方式1
int ages2[];//方式2
//System.out.println(ages1);//数组要进行初始化才能使用
}
}
数组的初始化
数组的初始化一旦完成,数组的长度就固定不变了,除非重新定义做初始化。即数组是定长的。
数组的初始化方式:
- 静态初始化;
- 动态初始化;
静态初始化操作:
特点:由我们自己来为每一个数组元素设置初始化值,而数组的长度由系统(JVM)决定。
语法:数组元素类型[ ] 数组名 = new 数组元素类型[ ] {元素1,元素2,元素3,…};
简单写法必须声明后紧跟初始化:数组元素类型[ ] 数组名 = {元素1,元素2,元素3,…};
//数组静态初始化
class ArrayInitDemo
{
public static void main(String[] args)
{
/*
语法:数组元素类型[ ] 数组名 = new 数组元素类型[ ] {元素1,元素2,元素3,...};
*/
int[] nums = new int[]{1,3,5,7,9};
//int[] nums = {1,3,5,7,9};//简单写法
System.out.println(nums.length);//数组的长度
nums = new int[]{2,4,8};//重新初始化
System.out.println(nums.length);//重新初始化后数组的长度
}
}
动态初始化操作:
由我们来设置数组的元素个数(数组长度),而每一个数组元素的初始值由系统决定。
语法:数组元素类型[ ] 数组名 = new 数组元素类型[lenth];
//动态初始化操作
class ArrayInitDemo1
{
public static void main(String[] args)
{
//语法:数组元素类型[ ] 数组名 = new 数组元素类型[lenth];
int[] ages = new int[5];//动态初始化
System.out.println(ages.length);//5
ages = new int[10];//再次初始化
System.out.println(ages.length);//10
}
}
何时选择静态和动态初始化:事先知道需要存储的数据时选静态初始化;事先不知道需要存储的数据时选动态初始化;