递归

  • 方法自己调用自己
  • 栈内存溢出错误:StackOverflowError
  • 合法的递归条件也有可能发生递归错误,压栈太深,导致溢出
  • 在实际开发中不建议使用递归,能用循环的尽量用循环,因为循环效率高,耗费的内存少,递归使用不当,会导致JVM死掉,但有时候,只能用递归实现。
  • 实际开发中,栈溢出错误怎么解决:
  • 先检查递归条件是否出错,若出错,修改至正确。
  • 条件没问题的话,需要手动调整JVM的栈内存初始化内存大小,可以将栈内存调整大一些。
  • (java -X)这个可以查看调整堆栈的大小参数。

java递归基础题

1、不用递归,编写程序,从控制台输入整数n,计算1~n的值

package javaproject0314;

import java.util.Scanner;
public class Test1 {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int a = scan.nextInt();
		scan.close();
		System.out.println(factorial(a));
	}
	public static int factorial(int n) {
		int sum = 0;
		for(int i = n;i>0;i--) {
			sum+=i;
		}
		return sum;		
	}
}

2、使用递归,编写程序,从控制台输入整数n,计算1~n的和

public static int factorial(int n) {
		if(n == 1) {
			return 1;
		}
		return n + factorial(n - 1);
	}

面向过程和面向对象

  • 什么是面向过程的开发方式?
  • 面向过程的开发方式主要的特点是:
  • 注重步骤,注重的是实现这个功能的步骤。
    第一步干什么,第二步干什么。注重实现功能的因果关系。
    因为A所有B
    因为B所以c
    因为c所以D
  • 面向过程中没有对象的概念。只是实现这个功能的步骤以及因果关系。
  • 面向过程有什么缺点?
  • 面向过程最主要是每一步与每一步的因果关系,其中A步骤因果关系到B步骤,A和B联合起来形成-一个子模块,子模块和子模块之间又因为因果关系结合在一起,假设其中任何一一个因果关系出现问题(错误),此时整个系统的运转都会出现问题。( 代码和代码之间的耦合度太高,扩展力太差。)往往耦合度高的扩展力就差。
    *用面向对象开发一台计算机:没有任何部件,所有都是融合在一起。任何一个部位出问题,整个计算机都不可使用,只能报废。
  • 面向过程有什么优点?
  • 对于小型项目(功能),采用面向过程的方式进行开发,效率较高。不需要前期进行对象的提取,模型的建立,采用面向过程方式可以直接开始千活。一上来直接写代码, 编写因果关系。从而实现功能。.
  • 什么是面向对象的开发方式?
  • 将现实世界分割成不同的单元,然后每个单元都是实现成对象,然后去动一下,让各个对象之间协作起来形成一个系统。更符合人类的思维方式,更容易让人接受。
  • 例如:
    对象张三”
    对象“香烟"
    对象“打火机”
    对象吸烟的场所"
    然后将以上的4个对象组合在一-起,就可以模拟-一个人的抽烟场景。
    其中张三”对象可以更换为李四”
    其中香烟"也可以更换品牌。
    其中打火机”也可以更换.
    其中“\吸烟的场所"也可以更换。
  • 采用面向对象的方式进行开发:耦合度低,扩展力强。
  • 面向过程主要关注的是:实现步骤以及整个过程。
    面向对象主要关注的是:对象A,对象B,对象C,然后对象ABc组合,或者CBA组合…
  • 当我们采用面向对象的方式贯穿整个系统的话,涉及到3三个术语:
    OOA:面向对象分析
    OOD:面向对象设计
    OOP:面向对象编程
    整个软件开发的过程,都是采用oo进行贯穿的。
    实现一个软件的过程:分析(A) --> 设计(D)–>编程§

类和对象

  • 什么是类?
  • 类实际上在现实世界当中是不存在的,是一个抽象的概念。是一个模板。是我们人类大脑进行思考、总结、抽象的一个结果。
  • 类就是一个模板:类中描述的是所有对象的共同特征信息”,本质上是某些事物具有共同特征,将这些特征提取出来形成的一个概念就是”类“。
  • 类->对象:实例化
  • 类 = 属性 + 方法
    属性来源于:状态
    方法来源于:动作
public class 明星类{
//属性-->状态,多见于名词
名字属性;
身高属性;
//方法-->动作,多见于动词.
打篮球方法() {
}
学习方法() {
}
}
  • 类的定义
  • 怎么定义一个类,语法格式是什么?
    [修饰符列表] class类名{
    // 类体-属性+方法
    // 属性在代码上以"变量"的形式存在(描述状态)
    // 方法描述动作/行为
    }
    注意:修饰符列表可以省略。
  • 为什么属性是以变量的形式存在的?
  • 假设我们要描述一个学生,学生包括哪些属性:
    学号:110.
    姓名:张三
    性别: 男
    住址:山东青岛市
    答案:属性对应的是数据,数据在程序中只能放在变量中,属性就是变量。
  • 变量的分类,变量根据出现位置进行划分:
  • 方法体当中声明的变量:局部变量。
  • 方法体外声明的变量:成员变量。
    *定义学生类
package javaproject0315;

/*1、观察学生对象的共同特征(只观察属性)
有哪些共同特征:
学号:采用int类型
姓名:采用string类型
年龄:
采用int类型
性别:采用char或者boolean类型
住址:采用string类型
注意:属性是成员变量。
2、以上是分析总结的结果,可以开始写代码了,定义Student类,编写成员变量作为属性特征、
3、变量特征:必须先生命,再赋值,才能访问 
 */
//Student既属于类名,又属于类型名
public class Student {

	public static void main(String[] args) {
		/*创建对象的语法是什么? 
		 * new类名(); 类是模板,
		 * 通过一个类,是可以创建N多个对象的。
		 * new是一个运算符。专门负贲对象的创建。
		 */		
		/*
		 * Student s1 = new Student() ;  和 int i = 100; 
		 * 解释一下: i是变量名, int是变量的数据类型,100是具体的数据。 
		 * s1是变量名(s1不能叫做对象。s1只是一个变量名字。) Student是变量s1的数据类型(引用数据类型)
		 * new Student()这是一个对象。(学生类创建出来的学生对象。) 
		 * 数据类型包括两种: 基本数据类型: byte short int long float double boolean char 
		 * 引用数据类型: string、 Student..... java中所有"类"都属于引用数据类型.
		 */
		//学号
		int number;
		//姓名
		String name;
		//年龄
		int age;
		//性别
		boolean gender;
		//地址
		String address;
	}
}
  • 什么是对象?
  • 对象是实际存在的个体。
  • 在java语言中,要想得到“对象",必须先定义“类","对象”"是通过类”这个模板创造出来的。
  • 对象就是通过类创建出的个体,对象也叫实例。通过创建对象的过程我们可以称为:创建,实例化
  • 对象->类:抽象
  • java程序员

java 清除递归产生的内存占用 java递归栈溢出解决方法_java 清除递归产生的内存占用

数组

  • 数组是一组有序的、具有相同数据类型的数据的集合,是一种引用数据类型,数组是有序的,可以分出先后,再内存中按照先后顺序立案续存储。
  • 根据组织数组的结构不同,可将其分为:一维数组、二维数组、…维数组。
  1. int intArray[] ;
  2. char[][] charArray;
  3. Student[] studentArray;
  4. String[][] args;
  • 一维数组的声明(定义)
    Java语言中一维数组的定义有两种方式:
    1.数据类型 数组名[];
    2.数据类型[] 数组名;
  • “数据类型”可以是Java中任意的数据类型,
    “数组名”为一个合法的标识符,“[]”指明该变量是一个数组类型变量并且是一维的。
  • Java在数组的定义中并不为数组元素分配内存,因此“[]”中不用指出数组中元素的个数即数组长度,而且对于如上定义的一个数组暂时还不能访问它的任何元素。
  • 一维数组的静态初始化:数组元素类型[] 数组名={元素1取值,元素2取值,…}
  • 当我们声明一个数组的同时对数组元素赋初值,称为数组的静态初始化。
  • 初值必须用大括号括起,用逗号作分隔符,初值的个数表示数组的大小。
  • 示例:1. Byte[] byteArray={1,2,3, 4,5}; 2. String[] strArray={ “1”,“6”“3”,“4"}; 3.byteArray. length=5; 4.strArray. length=4;
  • 相关说明:
  • 数组下标的下限为0,上限为数组元素个数减1。
  • 引用数组元素时,下标不能超出它的范围,通常Java会自动进行数组下标越界检查(出界例外:“IndexOutOfBoundsException”)。
  • 数组下标越界在程序编译时不会产生语法错误,数组下标越界是一个运行时异常
  • 编写程序时最好使用数组的length属性获得数组的大小,从而使数组下标不超出取值范围。
  • 数组元素可以用数组名和下标唯一确定。
  • 其一般形式为:数组名[下标] =与数组名同类型的常量、变量或表达式
  • cha[]charArray = {‘A’,‘B’,‘C’};
    charArray[0]=‘a’ ;
    charArray[1]=‘B’;
    charArray[2]=‘c’;
    charArray[3]=‘D’; //编译不报错,运行报错,超出范围
  • 例子,最后一个输出导致越界异常。
package javaproject0315;

import java.util.*;
public class Test1 {
	public static void main(String[] args) {
		int intArray[] = { 8,9,12, 13,14};
		int sum = 0;
		for (int i = 0;i <= intArray.length; i++) {
			sum += intArray[i];
			System.out.print("intArray[" + i + "]=" + intArray[i]+"  ");
			System.out.println("sum: " + sum);
		
	    }
	}
}

java 清除递归产生的内存占用 java递归栈溢出解决方法_System_02

  • 一维数组的动态初始化,用运算符new分配内存再赋值
  • 数据类型[] 数组名;
    数组名= new 数据类型[size] ;// size指明数组的长度
  • 示例:1. int intArray[]; 2. char[] charArray; 3. intArray=new int[5]; 4. // intArray[]=new int[5]; //程序将报错 5. charArray= new char[5]; 6. //charArray[] =new char[5];//程序将报错
  • 示例:1. int intArray[]=new int[5]; 2. intArray[0]= 100; 3. Person[] personArray= new Person[5] 4.personArray[3]=new Person( “Jack”
    002); 5.personArray[4]= new Person( “mary” ,001);
  • 相关说明
  • 用new为数组分配内存后,自动用数据类型的默认值初始化所有的数组元素。
  • 各类数据类型的默认值:整型为0,实型为0.0f或0.0d,字符型为‘\u000’类对象(引用类型)初始化为null;
  • 默认值和赋值示例:
package javaproject0315;

import java.util.*;
public class Test2 {
	public static void main(String[] args) {
		int i;
		int a[] = new int[5];
		for (i = a.length - 1;i >= 0;i--) {
			//隐含初值
			System.out.println("a[" + i + "]=" + a[i]);
		}
		for (i = 0; i < 5; i++) {
			//引用数组,重新赋值
			a[i] = i;
		}
		for (i = a.length - 1;i >= 0;i--) {
			System.out.println("a[" + i + "]=" + a[i]);
		}
		String[] strArray = new String[5];
		for (i = strArray.length - 1;i >= 0;i--) {
			//隐含初值null
			System.out.println("strArray[" + i + "]=" + strArray[i]); 			
		}
		strArray[0]	= new String("hello");
		strArray[1]	= new String("hello");
		strArray[2]	= new String("hello");
		strArray[3]	= new String("hello");
		strArray[4]	= new String("hello");
		for (i = strArray.length - 1;i >= 0;i--) {
			//引用数组,重新赋值
			System.out.println("strArray[" + i + "]=" + strArray[i]); 			
		}
	}
}
  • 结果
  • 数组对象的存储单元示意图
  • String s[]=new String[3];
    S[0]=new String( “abc” );
    S[1]=new String( “def” );
    S[2]=new String( “gh” );


  • 数组的拷贝
  • 数组创建后就不能改变它的大小,但是可以使用相同的引用变量指向一个全新的
    数组。
  • 示例:1.int[] elements = new int[6] ;
    2.elements = new int[10] ;
    3.int[] arr1 = new int[100];
    4.elements = arrl; //将产生语法错误
  • Java在System类中提供了一个特殊的方法,arraycopy( ),它实现数组之间的拷贝。
package javaproject0315;

import java.util.*;
public class Test3 {
	public static void main(String[] args) {
		int[] elements = {1,2,3,4,5,6};
		int[] hold = {12,11,10,9,8,7,6,5,4,3,2,1};
		//讲elements中的元素拷贝到hold中,从下标0开始
		System.arraycopy(elements, 0, hold, 0, elements.length);;
		for(int i = 0;i < elements.length;i++) {
			System.out.println("elements ["+ i +"] = "  + elements[i]);
		}
		for(int i = 0;i < hold.length;i++) {
			System.out.println("hold ["+ i +"] = "  + hold[i]);
		}
	}
}
  • 一维数组小结
  • 数组中的每个元素具有相同的数据类型,数组元素可以是基本类型、复合类型(类对象)也可以是数组类型。
  • 数组要经过定义、分配内存及赋值后方可使用。
  • 根据数组名和下标来唯一地确定 数组中的元素。
  • 在Java中,定义数组时不必给出数组的大小,因为Java的数组是动态分配的。
  • 二维数组
  • Java将多维数组看作数组的数组。例如二维数组就是一个特殊的一维数组,它的每个元素是一一个一维数组。
  • 二维矩阵数组的–般说明格式为:
    数组元素类型数组名[][]=new数组元素类型[行数] [列数]
  • 举例:int b[][] =new int[3][];
    b.length=3;
    int a0[]={11};
    int a1[]={21,22};
    int a2[]={31,32,33};
    b[0]=a0; //b[0].length=1;
    b[1]=a1; //b[1].length=2;
    b[2]=a2; //b[2].length=3;
  • 二维数组有一个好处是第二维的长度可以不相等,int b[][]={{11}, {21, 22}, {31, 32, 33}}
  • 二维数组元素的访问
    B[0][0]=11;
    B[1][0]=21;
    B[3][2]=33;
  • 正确的说明示例
    int al[][ ] =new int [2][3];
    int a2[][] = new int [2][];
    int a3[][] =new int [4][6];中括号可以放在变量的左边或者右边

java数组基础题

** 1、将用户输入的六个数字填入数组并找出数组中最大值和最小值
输入描述:
随机输入的6个整数
输出描述:
输出数组中的最大值,最小值(最大值最小值之间用空格隔开。若有多个最大值或最小值,输出一次即可 **

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        int[] ary = new int[6];
        int max;
        int min;
        Scanner scanner = new Scanner(System.in);
     	for (int i = 0; i <ary.length ; i++) {
            ary[i]=scanner.nextInt();
        }
        max = ary[1];
		min = ary[1];
		for (int i = 0;i <ary.length;i++) {
			max = Math.max(ary[i], max);
			min = Math.min(ary[i], min);
		}				
		scanner.close();
        System.out.println(max+" "+min);
    }
}

** 2、输入6个整数,先将其输出然后再将数组倒转,再次输出数组
输入描述:
用户随机输入的6个int类型变量
输出描述:
先输出用户输入顺序的数组(这一步预设代码已给出)
再输出反转后的数组**

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        int[] arr = new int[6];
        Scanner scanner = new Scanner(System.in);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = scanner.nextInt();
        }
        System.out.println(Arrays.toString(arr));
        for (int i = 0; i < arr.length; i++) {
            int temp = arr[i];
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
            if (i == arr.length - i - 2) {
                break;
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

** 3、给定一个二维数组,请你编写一个求和函数,计算出这个数组元素的和
输入描述:

输出描述:
输出二维数组元素的和**

public class Main {
    public static void main(String[] args) {
        int[][]  arr = {{11, 33, 55}, {22, 44, 66, 88}, {131, 214, 315, 146}, {928, 827, 726, 625}, {424, 525}};
        int sum = add(arr);
        System.out.println(sum);
    }

    public static int add(int[][] arr) {
        int sum = 0;
        for (int i = 0; i < arr.length; i++)
            for (int j = 0; j < arr[i].length; j++) {
                sum = sum + arr[i][j];
            }
        return sum;
    }
}