zoukankan      html  css  js  c++  java
  • Java 方法调用 方法重载 方法递归

    方法的调用

    /*
        以下程序不使用”方法“,分析程序存在那些缺点?
        一下的代码都是完成int类型数据的和,相同的代码写了三遍。(只不过每一次参与求和的数据不通)
        代码没有得到重复使用
        应该在java语言当中有这样的一种机制:
            - 某个功能代码只需要写一边。
            - 要使用这个功能,只需要给这个功能传递具体的数据
            - 这个功能完成之后返回一个最终的结果,
            这样代码就可以重复利用了,提高代码复用性【这就是”方法“】
        使用这个方法我们称为”调用/invoke“
    */
    
    public class MethodTest01
    {
        public static void main(String[] args){
            // 需求1;请编写程序计算10和20的和,并将结果输出【功能:计算两个int类型数据的和】
            int a = 10;
            int b = 20;
            int c = a + b;
            System.out.println(a + " + " + b + " = " + c);
    
            // 需求2:请编写程序计算666和888的和,并将结果输出【功能:计算两个int类型数据的和】
            int x = 666;
            int y = 888;
            int z = x + y;
            System.out.println(x + " + " + y + " = " + z);
    
            // 需求3:请编写程序计算111和222的和,并将结果输出【功能:计算两个int类型数据的和】
            int m = 111;
            int n = 222;
            int e = m + n;
            System.out.println(m + " + " + n + " = " + e);
    
            // 以上的三个需求其实就是一个需求,这个需求是:计算两个int类型数据的和,功能相同。只不过每一次参与计算的具体数据不同。
        
        }
    }
    /*
        以下直接使用方法这种机制【这个例子不讲方法的语法】,分析程序的优点?
            代码得到了重复使用
        方法的本质是什么?
            方法就是一段代码片段,并且这段代码片段
            可以完成某个特定的功能,并且可以被重复的使用。
        方法,对应的英语档次:method
        方法在C语言中叫函数/Function
    
        方法定义在类体当中,在一个类当中可以定义多个方法,方法编写的位置没有先后顺序,可以随意。
    
        方法体当中不能定义方法!!!!!
    
        方法体由java语句构成,方法体当中的代码遵守自上而下的顺序依次执行。
    */
    public class MethodTest02
    {
        // 类体
        public static void main(String[] args){
            // 计算两个int类型数据的和
            MethodTest.sumInt(10,20);
            MethodTest.sumInt(100,200);
            MethodTest.sumInt(111,222);
    
            
        }
        // 方法
        // 单独的定义一个方法
        // 该方法完成计算两个int类型数据的和,并且将结果输出
        public static void sumInt(int a,int b){
            int c = a + b;
            System.out.println(a + " + " + b + " = " + c);
        }
    }
    /*
        关于java语言当中的方法:
            1、方法怎么定义,语法结构;
                [修饰符列表]返回值类型 方法名(形式参数列表){
                    方法体;
                }
    
            2、对以上的语法结构进行解释说明:
                - 关于修饰符列表
                    * 可选项,不是必须的
                    * 目前统一写成:public static 【以后解释】
                    * 方法的转修符列表中有"static关键字"的话,怎么调用这个方法?
                        类名.方法名(实际参数列表);
                - 返回之后类型
                    * 什么是返回值?
                        一个方法是可以完成某个特定功能的,这个功能结束之后大多数都是需要返回最终执行结果的,执行结果可能是一个具体存在的数据。
                        而这个具体存在的数据就是返回值。
                    * 返回值类型?
                        返回值是一个具体存在的数据,数据都是有类型的,此处需要指定的是返回值的具体类型
                    * 返回值类型都可以指定那些类型呢?
                        java任意一种类型都可以,包括基本数据类型和所有的引用数据类型。
                    * 也可能这个方法执行结束之后不返回任何数据,java中规定,当一个方法执行结束之后不返回任何数据的话,返回值类型位置必须编写:void关键字。
    
                    * 返回值类型可以是:
                        byte、short、int、long、float、double、boolean、char、String、void.......
                    
                    * 返回值类型若不是void,表示这个方法执行结束之后必须返回一个具体的数值。
                        当方法执行结束的时候没有返回任何数据的话编译器报错,怎么返回值呢,代码怎么写呢?
                        "return 值;",并且要求"值"的数据类型必须和"方法的返回值类型"一致,不然编译器报错.
                    * 返回值类型是void的时候,在方法当中不能编写"return 值;" 这样的语句。但是要注意可以编写"return;"这样的语句
                    * 只要带有return关键字的语句执行,return语句所在的方法结束。【不是JVM结束,是return所在方法结束】
    
                - 方法名:
                    * 只要是合法的标识符就行
                    * 方法名最好见名知意
                    * 方法名最好是动词
                    * 方法名首字母要求小写,后面每个单词首字母大写
    
                - 形式参数列表:简称形参
                    * 形参是局部变量:int a; double b; float c; String s;....
                    * 形参的个数可以是:0-N个
                    * 多个形象之间用“逗号”隔开
                    * 形象中起决定性作用的是形参的数据类型,形参的名字就是局部变量的名字。
                    * 方法在调用的时候,实际给这个方法传递的真实数据被称为:实际参数,简称实参
                    * 实参列表喝形参列表必须满足:
                        数量相同
                        类型对应相同
    
                        例如:
                            方法定义
                            public static int sum(int a,int b){  // (int a, int b)是形参列表
                            }
                            方法调用
                            sum("abc","def"); // 编译器报错
                            sum(10,20);  // (10,20)是实参列表
    
    
                - 方法体必须由大括号括起来,方法体当中的代码有顺序,遵循自上而下的循序依次执行
                    并且方法体由java语句构成,每一个java语句以";"结尾
    
            3、方法怎么调用?
                - 方法只定义不去调用时不会执行的,只要在调用的时候才会执行。
                - 语法规则:【方法的修饰符列表当中有static】
                    类名.方法名(实参列表); <这是一条java语句,表示调用某个类的某个方法,传递这样的实参。>
    
    */
    
    
    // public 表示公开的
    // class 表示定义类
    // MethodTest是一个类名
    public class MethodTest03    // 表示定义一个公开的类,起名MethodTest,由于是公开的类,所以源文件名必须, MethodTest.java
    {
        // 类体
        // 类体中不能不直接编写java语句,除声明变量之外
    
        // 方法
        // public 表示公开的
        // static 表示静态的
        // void 表示方法执行结束之后不返回数据
        // main 是方法名:朱方法
        // (String[] agrs): 形式参数列表,其中String[] 是一种应用数据类型,args是一个局部变量的变量名
        // 所以以下只有args这个局部变量的变量名是随意的
        // 主方法就需要这样固定编写,这是程序的入口,【SUN规定的,必须这样写】
    
        
        public static void main(String[] args){
    
            // 这里的程序是一定会执行的
            // main方法是JVM负责调用,是一个入口位置
            // 从这里作为起点开始执行程序
            // 既然是这样,我们就可以在这里编写java语句来调用其它的方法
            // 调用MethodTest的sum方法,传递两个实参
            MethodTest.sum(10,20);    // (10,20)实参列表 【实际上执行到这里main方法暂停了,进入sum方法执行,sum方法执行结束之后表示main方法第一次调用结束】
    
            // 注意:方法体当中的代码是顺序的,遵循自上而下的顺序依次执行
    
            // 一个方法可以重复使用,重复调用
            int a = 100;
            MethodTest.sum(a,500); // (a,500)实参列表
    
            // 再次调用方法
            int k = 90;
            int f = 10;
            MethodTest.sum(k,f);  // (k,f)实参列表
        }
    
    
        // 自定义发放,不是程序的入口
        // 方法作用:计算两个int类型数据的和,不要求返回结果,但是要求将结果直接输出到控制台
        // 修饰符列表:public static
        // 返回值类型:void
        // 方法名:sum
        // 形式参数列表:(int x,int y)
        // 方法体:主要任务是求和之后输出计算结果
        public static void sum(int i,int j){    // (int i, int j)形参列表
            System.out.println(i + " + " + j + " = " + (i+j));
        }
    }
    /*
        方法的调用不一定在main方法当中,可以在其他方法当中
        只要是程序可以执行到的位置,都可以去调用其它方法
    */
    public class MethodTest04
    {
    
        public static void sum(int a,int b){
            System.out.println(a + " + " + b + " = " + (a+b));
    
            // 调用doSome方法
            MethodTest.doSome();
        }
    
        // 主方法
        public static void main(String[] args){
    
            // 调用sum方法
            MethodTest.sum(1,2);
            System.out.println("hello world!");
        }
    
        public static void doSome(){
            System.out.println("do some!");
        }
    
    }
    /*
        方法调用的时候实参和形参要求个数对应相同,数据类型对应相同
        类型不痛的时候要求能够进行相应的自动类型转换
    */
    public class MethodTest05
    {
    
        public static void main(String[] args){
    
            // 编译错误:参数数量不通
            // MethodTest.sum();
            
            // 编译错误:实参和形参的类型不是对应相同的
            // MethodTest.sum(true,false);
    
            // 可以
            MethodTest.sum(10L,20L);
    
            // 存在自动类型转换:int--> long
            MethodTest.sum(10,20);
    
            // 编译错误:参数类型不是对应相同的
            // MethodTest.sum(3.0,20);
    
            // 可以
            MethodTest.sum((long)3.0,20);
        }
    
        public static void sum(long a,long b){
            System.out.println(a + " + " + b + " = " + (a+b));
        }
    
    }
    /*
        方法调用
            1、方法的修饰符列表当中有static关键字,完整的调用方式是:类名.方法名(实参列表);
    
            2、但是,有的时候“类名.”可以省略,什么情况下可以省略呢?
                m1(){
                    m2();
                }
                m1方法和m2方法在同一个类体当中的时候,“类名.”可以省略不写
         3、建议在一个java源文件当中只定一个class,比较清晰,这里只是为了方便才在一个java源文件当中编写多个class,这种方式不要模仿
    */ public class MethodTest06 { public static void main(String[] args){ // 调用方法 MethodTest.m(); // 对于方法的修饰符列表当中有static关键字的:“类名.”可以省略不写吗? m(); // 调用其它类【不是本类中的】中的方法 A.doOther(); // 省略“类名.”试试 // 编译报错,“类名.”省略之后,默认从前类中找“doOther”方法,在当前类中该方法不存在。 // doOther(); } public static void m(){ System.out.println("m method execute!"); // 完整的方式 MethodTest.m2(); // 省略的方式 m2(); // 不想调用当前本类当中的m2方法,这个时候就必须添加“类名.”了。 A.m2(); } public static void m2(){ System.out.println("m2 execute!"); } } class A { public static void doOther(){ System.out.println("'A' s doOther method invoke!"); } public static void m2(){ System.out.println("'A' s m2 method execute!"); } }
    /*
        分析以下程序的输出结果
            main begin
            m1 begin
            m2 begin
            m3 begin
            m3 over
            m2 over
            m1 over
            main over
    
            对于当前的程序来说:
                main方法最先被调用,main方法也是最后一个结束
                最后调用的方法是m3方法,该方法最先结束
            main方法结束之后,整个程序结束了【这句话只适合于当前所讲内容】
    
            不用刻意去记忆:
                只要记住方法中的代码是自上而下的循序依次执行即可。
                当前行的程序在没有结束的时候,下一行的代码是无法执行的。
    */
    public class MethodTest07
    {
        public static void main(String[] args){
            System.out.println("main begin");
            m1();    
            System.out.println("main over");
        }
    
        public static void m1(){
            System.out.println("m1 begin");
            m2();    
            System.out.println("m1 over");
        }
    
        public static void m2(){
            System.out.println("m2 begin");
            m3();    
            System.out.println("m2 over");
        }
        
        public static void m3(){
            System.out.println("m3 begin");
            System.out.println("m3 over");
        }
    
    }
    /*
        方法的返回值类型不是void的时候。
            1、返回值类型不是void的时候:要求方法必须保证百分百执行“return 值;”这样的语句来完成值返回
            没有这个语句编译器会报错。
            2、一个方法有返回值的时候,当我们调用这个方法的时候,方法返回了一个值,对于调用者来说,这个返回值可以选择接收,也可以选择不接受
            但是大部分情况下我们都是选择接收的
    */
    public class MethodTest08
    {
        public static void main(String[] args){
            // 调用方法
            divide(10,3); // 这里没有接收这个方法的返回数据
            
            // 这里接收一下方法执行的结束之后的返回值
            // 采用变量接收
            // 变量的数据类型需要和返回值的数据类型相同,或者可以自动类型转换,
            // boolean b = divide(10,3); // 编译报错,类型不兼容
            
            // 赋值运算符的右边先执行,将执行结果赋值左边的变量
            int i = divide(10,3);
            System.out.println(i);
    
            long x = divide(10,3);
            System.out.println(x);
    
            System.out.println(divide(10,3));
    
    
        }
    
        /*
            需求:
                请定义并实现一个方法,该方法可以计算两个int类型数据的商
                要求将最终的计算结果返回给调用者
        */
        // 编译报错:缺少返回语句
        /*
        public static int divide(int a,int b){
        }
        */
    
        // 编译报错:缺少返回值
        /*
        public static int divide(int a,int b){
            return;
        }
        */
    
        // 编译报错:方法定义的时候要求返回一个int类型,此时返回布尔类型,类型不兼容
        /*
        public static int divide(int a,int b){
            return true;
        }
        */
    
    
        // 可以:但是具体的方法体中编写的代码无法满足当前的需求
        /*
        public static int divide(int a,int b){
            return 1;
        }
        */
    
        
    
    
        public static int divide(int a,int b){
            int c = a / b;
            return c;
        }
    
    
    }
    /*
        深入return语句
            - 带有return关键字的java语句只要执行,所在的方法执行结束
            - 在”同一个作用域“当中,return语句下面不能编写任何代码,因为这些代码永远都执行不到,所以编译报错
        
    */
    public class MethodTest09
    {
        public static void main(String[] args){
            /*
                int retValue = m();
                System.out.println(retValue);
            */
    
            // 编译报错,调用方法,方法名后面有括号;
            // System.out.println(m);
    
            System.out.println(m());
    
        }
    
        // 编译报错:缺少返回语句,以下程序编译器认为无法百分百保证”return 1;“ 会执行。
        // 无法百分百保证”return 1;“会执行
        /*
        public static int m(){
            int a = 10;
            if(a > 3){
                return 1;
            }
        }
        */
    
        // 以下程序可以保证”return 1; 或 return 0;“执行,编译通过 
        /*
        public static int m(){
            int a = 10;
            if(a > 3){
                return 1;
            }else{
                return 0;
            }
        */
    
        // 可以,和以上方法完全相同
        /*
        public static int m(){
            int a = 10;
            if(a > 3){
                return 1;
            }
            return 0;
        }
        */
    
        /*
        public static int m(){
            int a = 10;
            if(a > 3){
                return 1;
                // 这里不能编写代码,编译报错,因为无法访问的语句
                // System.out.println("hello");
            }
            // 这里的代码可以执行到
            // System.out.println("hello");
            return 0;
        }
        */
    
        public static int m(){
            // return 10 > 3 ? 1 : 0;
            return 2 > 3 ? 1 : 0;
        }
    
    }
    /*
        在返回值类型是void的方法当中使用”return;“语句。
        ”return;“语句出现在返回值为void的方法当中主要是为了用来结束当前方法
    */
    public class MethodTest10
    {
        public static void main(String[] args){
    
            m();
            
            
            for(int i =10; i>0;i--){
                if(i == 2){
                    return;  // 结束的是main方法
                }
                System.out.println("data: -->" + i);
            }
            System.out.println("Exeoute Here!");
    
            // 编译报错,返回值类型是void,不能返回值。
            // return 100;
            
        }
    
        // 编译错误:对于结果类型为空的方法,无法返回值
        /*
        public static void m(){
            return 10;
        }
        */
    
        /*
        public static void m(){
            return;
        }
        */
    
        public static void m(){
            for(int i = 0;i<10;i++){
                if(i==5){
                    return;  // 不是终止for循环,终止的是m()方法。
                    // break; // 终止的for循环
                }
                System.out.println("i -->" + i);
            }
            System.out.println("hello world");
        }
    
    }
    /*
        方法在执行过程当中,在JVM中的内存是如何分配的呢,内存是如何变化的?
            1、方法只定义,不调用,是不会执行的,并且在JVM中也不会给该方法分配运行所属的内存空间,
            只有在调用这个方法的时候,才会动态的给这个方法分配所属的内存空间
            
            2、在JVM内存划分上有这样三块主要的内存空间:(当然除了这三块之外还有其它的内存空间)
                - 方法区
                - 堆内存
                - 栈内存
            3、关于栈数据结构:
                - 栈:stack,是一种数据结构
                - 数据结构反应的是数据的存储形态
                - 数据结构是独立的学科,不属于任何编程语言的范畴,只不过在大多数编程语言当中要使用数据结构
                - 作为程序员需要提前精通:数据结构 + 算法【计算机专业必修一门课】
                - java程序员在不精通数据机构和算法的前提下,也可能进行java开发,因为java有一套庞大的类库支撑,别人写好了,直接用【JavaSE当中的集合章节使用了大量的数据结构】
                - 常用的数据结构:
                    * 数组 * 队列 * 栈 * 链表 * 二叉树 * 哈希表/散列表...
            4、方法代码片段存在哪里?方法执行的时候执行过程内存在哪里分配?
                - 方法代码片段属于.class字节码文件的一部分,字节码文件在类加载的时候,将其放到了方法区当中,所以JVM中的三块主要的内存空间中方法区内存最先有数据,存放了代码片段
                - 代码片段虽然在方法区内存当中只有一份,但是可以被重复调用。
                    每一次调用这个方法的时候,需要给该方法分配独立的活动场所,在栈内存中分配。【栈内存中分配方法运行的所属内存空间】
            5、方法在调用的瞬间,会给该方法分配独立的内存空间,会在栈中发生压栈动作,
            方法执行结束之后,该方法分配的内存空间全部释放,此时发生弹栈动作。
                - 压栈:给方法分配内存
                - 弹栈:释放该方法的内存空间
            6、局部变量在”方法体“中声明。局部变量运行阶段内存在栈中分配。
                
    */
    
    
    
    public class MethodTest
    {
        public static void main(String[] args){
            m();
    
        }
    
        public static void m(){
            int i = 10;
        }
    
    }

     
    // 注意:在EditPlus当中,字体颜色为红色的表示一个类的名字,并且这个类是JavaSE类库中自带的。
    // 我们自定义的类MethodTest,字体颜色是黑色,是标识符
    // 其实JavaSE类库中自带的类,例如:String.class、System.class,这些类的类名也是标识符
    // 只要是类名就一定是表示符
    
    
    // 重点:方法调用的时候,在参数传递的时候,实际上传递的是变量中保存的那个“值”传过去的
    public class MethodTest
    {
        public static void main(String[] args){
            int a = 10;
            int b = 20;
    
            int retvalue = sumInt(a,b);
    
            System.out.println("retValue = " + retvalue);
        }
    
        public static int sumInt(int i,int j){
            int result = i + j;
            int num = 3;
            int retValue = divide(result,num);
            return retValue;
        }
    
        public static int divide(int x ,int y){
            int z = x / y;
            return z;
        }
    
    }
    
    /*
        画图依据:
            1、只要涉及到到参数传递的问题,传递的是变量中保存的值
            2、画图的时候,必须遵循“方法自上而下的顺序依次执行”这个原则
    */
    // 分析以下程序的输出结果【画图分析】
    // 画图应该这样画?
    // 程序执行一步,在图上体现一步即可。
    public class MethodTest
    {
        public static void main(String[] args){
            int i = 10;
            method(i);
            System.out.println("main --> " + i);
        }
    
        public static int method(int i){
            i++;
            System.out.println("method --> " + i);
        }
    }

    方法重载

    /*
        以下代码不使用“方法重载机制”,不适用overload,分析程序存在的缺点?
            1、sumInt,sumDouble,sumLong方法虽然功能不通,但是功能是相似的,都是求和。
            在以下程序当中功能相似的方法,分别起了三个不同的名字
            这对于程序员来说,调用方法的时候不方便,程序员需要记忆更多的方法,才能完成调用【不方便】
            2、代码不美观
        有没有这样的一种机制:
            功能虽然不同,但是“功能相似”的时候,有没有这样的一种机制,可以让程序员使用这些方法的时候就像在使用同一个方法一样
            这样程序员以后编写代码比较方便,也不需要记忆更多的方法名,代码也会很美观。
    
            有这种机制:方法重载机制/Overload
    */
    
    public class OverloadTest
    {
        // 入口
        public static void main(String[] args){
            // 调用方法
            int result1 = sumInt(1,2);
            System.out.println(result1);
    
            double result2 = sumDouble(1.0,2.0);
            System.out.println(result2);
    
            long result3 = sumLong(1L,2L);
            System.out.println(result3);
    
        
        }
    
        // 定义一个方法,可以计算两个int类型数据的和
        public static int sumInt(int a,int b){
            return a + b;
        }
    
        // 定义一个方法,可以计算两个double类型数据的和
        public static double sumDouble(double a,double b){
            return a + b;
    
        }
        // 定义一个方法,可以计算两个long类型数据的和
        public static long sumLong(long a,long b){
            return a + b;
        }
    
        // 最终希望达到的效果是:程序员在使用上面的相似的方法的时候,就像再用一个方法一样
        // Java支持这种机制【有些语言不支持,例如以后要学习的:Javascript】
    
    }
    /*
        该程序还是一个体验程序,体验一下方法重在的有点:
            - 程序员调用方法的时候,比较方便,虽然调用的是不通的方法,但是就感觉在使用一个方法一样
            不需要记忆更多的方法名
            - 代码美观
        前提:功能相似的时候,方法名可以相同
        但是,功能不通的时候,尽可能让这两个方法的名字不同
    */
    
    public class OverloadTest
    {
        public static void main(String[] args){
    
            // 调用方法的时候就像在使用一个方法一样
            // 参数的类型不同,对应调用的方法不同,此时区分方法不再依靠方法名了,依靠的是参数的数据类型。
            System.out.println(sum(1,2));    
            System.out.println(sum(1.0,2.0));
            System.out.println(sum(100000000000L,200000000000L));
        
        }
    
        // 以下三个方法构成了方法重载机制
        public static int sum(int a,int b){
            System.out.println("int");
            return a + b;
        }
        public static long sum(long a,long b){
            System.out.println("long");
            return a + b;
        }
        public static double sum(double a,double b){
            System.out.println("double");
            return a + b;
        }
    }
    /*
        方法重载:
            1、方法重载又被称为:overload
    
            2、什么时候考虑使用方法重载?
                - 功能相似的时候,尽肯让方法名相同
                但是:功能不通/不相似的时候,尽可能让方法名不同。
            
            3、什么条件满足之后构成了方法重载?
                - 在同一个类当中
                - 方法名相同
                - 参数列表不同:
                    * 数量不同
                    * 顺序不同
                    * 类型不通
            
            4、方法重载和什么有关系,和什么没有关系?
                - 方法重载和方法名+参数列表有关系
                - 方法重载和返回值类型无关
                - 方法重载和修饰符类型无关
    */
    
    public class OverloadTest
    {
        public static void main(String[] args){
            m1();
            m1(10);
    
            m2(1,2.0);
            m2(2.0,1);
    
            m3(10);
            m3(3.0);
        }
    
        // 以下两个方法构成重载
        public static void m1(){}
        public static void m1(int a){}
    
        // 以下两个方法构成重载
        public static void m2(int a,double b){}
        public static void m2(double a,int b){}
    
        // 以下两个方法构成重载
        public static void m3(int x){}
        public static void m3(double y){}
    
        
        // 编译错误:以下不是方法重载,是发生了方法重复、
        /*
        public static void m4(int a,int b);
        public static void m4(int b,int a);
        
    
        public static void x(){}
    
        public static int x(){}
    
        void y (){}
    
        public static void y(){}
        
        */
    }
    /*
        方法重载的具体应用
    */
    
    public class OverloadTest
    {
        public static void main(String[] args){
            U.p(10);
            U.p(false);
            U.p("abc");
            U.p(3.0);
        }
    
    }
    
    
    // 自定义类
    class U
    {
        public static void p(byte b){
            System.out.println(b);
        }
        public static void p(short b){
            System.out.println(b);
        }
        public static void p(int b){
            System.out.println(b);
        }
        public static void p(long b){
            System.out.println(b);
        }
        public static void p(float b){
            System.out.println(b);
        }
        public static void p(double b){
            System.out.println(b);
        }
        public static void p(boolean b){
            System.out.println(b);
        }
        public static void p(char b){
            System.out.println(b);
        }
        public static void p(String b){
            System.out.println(b);
        }
    
    }

    方法递归

    /*
        关于方法的递归调用
            1、什么是递归?
                方法自身调用自身
                a(){
                    a();
                }
            2、递归是很耗费栈内存的,递归算法可以不用的时候尽量别用
    
            3、以下程序运行的时候发生了这样的一个错误【不是异常,是错误Error】:
                java.lang.StackOverflowError
                栈内存溢出错误
                错误发生无法挽回,只有一个结果,就是JVM停止工作。
            4、递归必须有结束条件,没有结束条件一定会发生栈内存溢出错误
            5、递归即使有了结束条件,即使结束条件是正确的,也可能会发生栈内存溢出错误,因为递归的太深了
            注意:
                递归可以不使用尽量别用
                但是有些情况下该功能的实现必须依靠递归方式
    */
    
    public class RecursionTest
    {
        // 主方法
        public static void main(String[] args){
            
            System.out.println("main begin");
            // 调用doSome方法
            doSome();
            System.out.println("main over");
        }
    
        // 以下的代码片段虽然只有一份
        // 但是可以被重复的调用,并且只要调用doSome方法就会在栈内存中重新分配一块所属的内存空间。
        public static void doSome(){
            System.out.println("doSome begin");
            doSome(); // 这行代码不结束,下一行程序是不能执行
    
            System.out.println("doSome over");
        }
    
    }
    /*
        不使用递归,计算1~~N的和【可以不用递归,尽量不用递归】
    */
    
    public class RecursionTest
    {
        public static void main(String[] args){
    
            /*
            // 1~4的和
            int sum = 0;
            for(int i=1;i<=4;i++){
                sum += i;
            }
            System.out.println("sum = " + sum);
    
            */
    
            // 直接调用方法即可
            int n = 4;
            int retValue = sum(n);
            System.out.println(retValue);
    
            n = 10;
            retValue = sum(n);
            System.out.println(retValue);
        }
    
        // 单独的定义一个方法,这是一个独立的功能,可以完成1~N的求和
        public static int sum(int n){
            int result = 0;
            for(int i=0;i<=n;i++){
                result += i;
            }
            return result;
        }
    }
    /*
        使用递归计算1~N的求和
            1 + 2 + 3 + 4
            4 + 3 + 2 + 1 n的最初值是4,建议采用这种方式
    */
    
    public class RecursionTest
    {
        public static void main(String[] args){
    
            // 1~4的和
            int n = 4;
            int retValue = sum(n);
            System.out.println(retValue);
        }
    
        public static int sum(int n){
            if (n == 1)
            {
                return 1;
            }
            return n + sum(n-1);  // 先运算sum(n-1),在跟n相加
            
    
        }
    }

    /*
        先不使用递归,计算N的阶乘
        5的阶乘
            5 * 4 * 3 * 2 * 1
    */
    
    
    /*
    public class RecursionTest
    {
        public static void main(String[] args){
    
    
            int n = 5;
            int Net = method(n);
            System.out.println(Net);
        }
    
        public static int method(int n){
            int sum = 1;
            for(int i=n;i>0;i--){
                sum = sum * i;
            }
            return sum;
        }
    }
    */
    
    
    // 递归方式
    // 不懂递归的,必须将以下的程序记住,因为面试题有出
    public class RecursionTest
    {
        public static void main(String[] args){
    
    
            int n = 5;
            int Net = method(n);
            System.out.println(Net);
        }
    
        public static int method(int n){
            if (n == 1){
                return 1;
            }
            return n * method(n-1);
        }
    }
    /*
        先不使用递归,计算N的阶乘
        5的阶乘
            5 * 4 * 3 * 2 * 1
    */
    
    
    /*
    public class RecursionTest
    {
        public static void main(String[] args){
    
    
            int n = 5;
            int Net = method(n);
            System.out.println(Net);
        }
    
        public static int method(int n){
            int sum = 1;
            for(int i=n;i>0;i--){
                sum = sum * i;
            }
            return sum;
        }
    }
    */
    
    
    // 递归方式
    // 不懂递归的,必须将以下的程序记住,因为面试题有出
    public class RecursionTest
    {
        public static void main(String[] args){
    
    
            int n = 5;
            int Net = method(n);
            System.out.println(Net);
        }
    
        public static int method(int n){
            if (n == 1){
                return 1;
            }
            return n * method(n-1);
        }
    }
  • 相关阅读:
    Centos常用快捷键
    ngnix笔记
    转载申明
    Linux 最小安装常用包
    update-alternatives关键解疑
    使用Java语言开发机器学习框架和参数服务器
    storm实践
    JVM线程状态,park, wait, sleep, interrupt, yeild 对比
    PHP版本解密openrtb中的价格
    Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/Axianba/p/14948452.html
Copyright © 2011-2022 走看看