递归
- 方法自己调用自己
- 栈内存溢出错误: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程序员
数组
- 数组是一组有序的、具有相同数据类型的数据的集合,是一种引用数据类型,数组是有序的,可以分出先后,再内存中按照先后顺序立案续存储。
- 根据组织数组的结构不同,可将其分为:一维数组、二维数组、…维数组。
- int intArray[] ;
- char[][] charArray;
- Student[] studentArray;
- 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);
}
}
}
- 一维数组的动态初始化,用运算符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;
}
}