知识整体图示:
一、简介
Java的开发语言是c语言。
1995年由SUN公司正式推出,Oak-橡树是sun公司推出的第一个版本。
1.0-1.1-1.2(Applet、swing---GUI)-1.3-1.4-5.0(十个特性)-6-7.0-8(十个特性)-9。已经有十个版本。
1、版本介绍
1995年5月23日,Java语言诞生;
1996年1月,第一个JDK-JDK1.0诞生;
1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入Java技术;
1996年9月,约8.3万个网页应用了Java技术来制作;
1997年2月18日,JDK1.1发布;
1997年4月2日,JavaOne会议召开,参与者逾一万人,创当时全球同类会议纪录;
1997年9月,JavaDeveloperConnection社区成员超过十万;
1998年2月,JDK1.1被下载超过2,000,000次;
1998年12月8日,Java 2企业平台J2EE发布;
1999年6月,SUN公司发布Java三个版本:标准版(J2SE)、企业版(J2EE)和微型版(J2ME);
2000年5月8日,JDK1.3发布;
2000年5月29日,JDK1.4发布;
2001年6月5日,Nokia宣布到2003年将出售1亿部支持Java的手机;
2001年9月24日,J2EE1.3发布;
2002年2月26日,J2SE1.4发布,此后Java的计算能力有了大幅提升;
2004年9月30日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE1.5更名为Java SE 5.0;
2005年6月,JavaOne大会召开,SUN公司公开Java SE 6。此时,Java的各种版本已经更名,以取消其中的数字“2”:J2EE更名为Java EE,J2SE更名为Java SE,J2ME更名为Java ME;
2006年12月,SUN公司发布JRE6.0;
2009年12月,SUN公司发布Java EE 6;
2010年11月,由于甲骨文对Java社区的不友善,因此Apache扬言将退出JCP;
2011年7月28日,甲骨文发布Java SE 7;
2014年3月18日,甲骨文发表Java SE 8。
从今年开始,java开始每半年更新一次,分别是在每年的3月和9月。
2、技术结构
1.环境组件
Java语言具有跨平台的特点,java跨平台靠的是JVM的支持。
JVM —— Java虚拟机:针对每种操作系统开发了对应的Java虚拟机,Java程序在写好之后并不是直接在计算机上运行,而先交给对应JVM去进行翻译,JVM将代码翻译成当前机器能够读懂的语言,再运行。Java虚拟机不是跨平台的。
JVM (Java Virtual Machine):Java虚拟机,是Java语言能够跨平台的前提。
JRE (Java Runtime Environment):Java运行时环境。JRE中包含JVM和核心类库。
JDK (Java Development Kit):Java开发工具包。JDK中包含来JRE和开发工具。
到官网下载windows版本jdk的安装包,直接双击运行安装即可。
注意:C://program files---不要安装到这个目录下,安装目录中尽量不要出现空格或者特殊符号。不然容易出现不可预估的异常。
2.技术结构
JAVASE —— 标准版 —— J2SE
JAVAEE —— 企业版 —— J2EE
JAVAME —— 移动版 —— J2ME
JAVACARD —— 智慧卡
3.常用命令
javac
javac 要编译的文件名.class/包名.文件名.class
例如:
javac cn.xjd.Test.java
javac Text.java
javac -d 编译完成之后的存放路径 要编译的Java文件
javac -d E:\\ Demo.java
java
java calss文件名
java Test
java -cp class文件的存放路径 class文件的文件名
java -cp F:\\cn.com Demo
4.环境变量(environment variable)
给操作系统来指定一系列的运行参数的量。
①JAVA_HOME=JDK的安装路径
②Path=%JAVA_HOME%\bin;
③CLASSPATH=. 表示指定运行目录的。“.”表示当前目录。在JDK1.7以后这个变量可以不再设置。
如下图所示,为JAVA_HOME的配置方法,Path也是一样的,在系统变量和用户变量中配置均可。
3、入门程序(HelloWorld)
public class Demo {
public static void main(String[] args){
System.out.println(“Hello World ~~~”);
}
}
注意:
1. Java程序必须放到.java的文件中。
2. class的文件名和类名对应,每一个类在编译完成产生一个对应的class文件。
3. 一个类用public修饰,称之为是一个公共类,公共类要求类名和Java的文件名一致。一个java文件中可以写多个类,但是只能有一个公共类。
二、基础知识
1、关键字(keywords)
是指Java中一些赋予了特殊含义的单词。
Java中一共有50个关键字,其中2个保留字:const ,goto。
另外还有三个直接量:true、false、null。这三个官方已经将其从关键字的行列刨除了,但是还是具有关键字的特性,只是名字发生了改变。
关键字的考点跑不过直接量和保留字,所有的关键字都是小写的。大家留心。
用于定义数据类型的关键字 | |||||
class | interface | byte | short | int | long |
float | double | char | boolean | void | enum |
用于定义流程控制的关键字 | |||||
if | else | switch | case | default | while |
do | for | break | continue | return |
|
用于定义访问权限修饰符的关键字 | |||||
private | protected | public |
|
|
|
用于定义类、函数、变量修饰符的关键字 | |||||
abstract | final | static | synchronized |
|
|
用于定义类与类之间关系的关键字 | |||||
extends | implements |
|
|
|
|
用于定义建立实例、判断实例的关键字 | |||||
new | this | super | instanceof |
|
|
用于异常处理的关键字 | |||||
try | catch | finally | throw | throws |
|
用于包的关键字 | |||||
package | import |
|
|
|
|
其他修饰符关键字 | |||||
native | strictfp | transient | volatile | assert |
|
我在网上看到很多的面试练习题,都是关于定义数据类型值关键字的,最经典的如下:
下面几个不是Java中的关键字?
A.true B.false C.null D.int
答案是ABC这三个选项。
2、标识符(IDentifier)
在程序中自定义的名称。
1.定义规则
1.可以由字母、数字、_、$组成(虽然可以使用$命名,但是尽量减少使用)。
int a;
int a2;
int a_2;
int a_2$;
2.不允许以数字开头。
3.不允许使用关键字。
4.见名知义。
5.严格区分大小写。Demo demo
例如:
int ILoveJava;
int $20;
int Hello_World;
//这些都是正确的,更变态的名字“_____”这在java中是允许的。
int _______;
2.驼峰命名法
1>类名/接口名
是由多个单词组成,每个单词的首字母要大写。
例如:
public class PlayGame{}
class HelloWorld{}
2>变量名/方法名
由多个单词组成,第一个单词的首字母小写,其余单词的首字母大写。
例如:
public class Person{
public void playGame(){}
}
3>包名
由多个单词组成,每个单词之间用 . 隔开,所有单词一律小写。
例如:
package cn.xjd.example
public class Person{
public void playGame(){}
}
4>常量名
由多个单词组成,每个单词之间用 _ 隔开,所有单词一律大写。
例如:
package cn.xjd.example
public class Person{
private static final int DEFAULT_CAPACITY=0;
public void playGame(){}
}
例题
这个地方会有一个比较坑的题,而且是明坑:
下面那些可以作为Java标识符使用?
A.Class B.String C.main D.com.cn.list
答案是ABC。
3、注释
解释说明程序的文字。
1.分类
1>单行注释
单行注释也叫短注释,是程序中注释一行代码。
格式:// 注释文字
package cn.xjd.example
//这里可以加注释
public class Person{
//这里可以加注释
private static final int DEFAULT_CAPACITY=0;
//这里可以加注释
public void playGame(){
//这里可以加注释
}
}
2>多行注释
多行注释也叫块注释,一次将程序中的多行注释掉。
格式:/*注释文字*/
3>文档注释
文档注释可以将其中的注释文字提取出来形成HTML格式API文档。
格式:/**注释文字*/
使用javadoc命令可以将文档注释内容提取出来,能够使用此命令的类一定要是公共类。
命令格式:javadoc -d 表示存放的目录 提取的Java文件
2.作用
解释程序,辅助排错。
4、常量(constants)
一共有6类常量,整数、小数、字符、字符串、布尔、空。
1.整数常量
所有的整数。比如:4、100。
2.小数常量
所有的小数。比如:3.5、 80.1
3.字符常量
将一个字母、数字或者符号用‘’来标识起来的时候,构成了一个字符常量。比如:‘a’、 ‘+’。
4.字符串常量
将一个或者多个字符用“”来标识起来,就形成了字符串常量。比如:“abc”、 “”。
5.布尔常量
用于表示逻辑值。只有true、false。
6.空常量
只有一个值null。
5、进制
进制是一种计数方式。Java中常用的进制有:二进制、八进制、十进制、十六进制。
1.二进制(Bin:Binary:0b)
单位取值范围:0-1,规则:满二进一 。从JDK1.7开始,允许在程序中去标识一个二进制数字,以0b作为开头。例如:0b00011 、0B11001。
2.八进制(Oct:Octal:0)
单位取值范围:0-7,规则:满八进一。八进制需要以0作为开头标识。例如:06 、012。
3.十进制(Dec:Decimal)
单位取值范围:0-9,规则:满十进一。十进制作为我们常用的进制方式,不需要任何标识作为开头,也是Java中的默认进制。
4.十六进制(Hex:Hexagondecimal:0x)
单位取值范围:0-9,A-F(表示的是10-15),规则:满十六进一,例如:9+1=a f+1=10 。十六进制需要以0x作为开头标识,例如:0x23、0Xab。常见于内存地址。
5.进制转换
1>10转2
十进制向二进制转化:不断地除以2然后取余,将余数倒排。
2>2转10
二进制向十进制转化:从低位次开始,每位上乘以2的位次次幂,然后求和。
3>2转8
二进制向八进制转化:从低位次开始,每三位化为一组产生一个八进制数字,最高位不足三位,补0。三变一的过程。
4>8转2
八进制向二进制转化:一变三的过程。
5>2转16
二进制向十六进制转化:四变一的过程。
6>16转2
十六进制向二进制转化:一变四的过程。
6.进制转换图
6、变量(variable)
1.定义
用于记录或者存储数据的容器。
2.声明变量
Public class A{
Public static void main(String[] args){
//定义变量格式:
int i;
int i=5;
int i,j,k;
int i=3,j=4,k=5;
}
}
3.特点
1.需要指明数据类型。
2.变量在哪儿定义就在哪儿使用。
3.变量必须先定义后使用。
4.变量必须先给值后使用。
注意:声明和初始化时两个过程。
三、数据类型(data type)
1、基本数据类型
8种基本数据类型。各个基本类型之间是平等的,不存在大小和父子类的关系。它们之间的大小只是从存储数据所占用的空间来比较的。
1.数值型
1.在Java中,整数默认是int,小数默认为double。
2.如果一个整数超过了int的取值范围,需要加上L作为结尾标识是一个long类型的数据。
3.Float类型的小数结尾必须以f作为标识。
4.注意科学技术法。
1>整数型
四种类型:byte、short、int、long。
①byte
字节型:占1个字节的空间,取值范围:-27~27-1,即: -128~127 ,一共256个存储空间。这个需要死记。
byte=127;
byte=-128;
②short
短整型:占2个字节的空间,取值范围:-215~215-1 ,即:-32768~32767,一共65356个空间。
③int
整型:占4个字节的空间,取值范围:-231~231-1,即: -2.1*1010^2.1*1010。
Java中整数默认为int类型。
从JD1.7开始,允许在数字之间插入“_”作为间隔,在编译的时候会自动省略“_”。
int i=0b0011;
int i=0x23;
int i =100_000_000; //表示:100000000
④long
长整型:占8个字节的空间,取值范围:-263~263-1,即:-9*1018~9*1018。要求以L作为结尾进行标识。一般在使用的过程中,最好使用大写L,因为小写的容易和数字1混淆。
long l = 5L;//(大写后缀)
long l=5l;//(小写后缀)
2>浮点型
①float
单精度:占4个字节的空间,取值范围:-2127~2127,即:-3.4*1038~3.4*1038。要求以f作为结尾进行标识。
float f = 3.2f;
②double
双精度:占8个字节的空间,取值范围:21023~21023,即:-10308~10308。Java中小数默认为double类型。
//正确写法
double d = 4.6;
double d2 = 6.3d;
double d3 = 3.8D;
double d =3e4;->double d = 30000.0;//十进制的科学计数法的表现形式。
double d=3p2;//十六进制的科学计数法的表示形式。
3>科学计数法
十进制的科学计数法:
3.1 * 1010
double d = 3.1e10;
十六进制的科学计数法:
3 * 25
double d2 = 0x3p5;
注意:Java中的数值类型都是有符号的。
2.字符型
1>char
字节型:占2个字节的空间,取值范围: 0~216-1 ,即:0~65535。不允许定义空字符。
char c = 'a';
char c = '中';
char c = ''; //不允许定义空字符
char c='\t';
默认值:’\u0000’:表示’’。以\u开头表示这个字符是他对应的UTF-8的编码。
字符可以按照码表对应成数字。
编码:
阿斯科玛表:ASC11,0-127。
西欧码表:ISO8859-1,0-255。
GB2312:前256位都只占1个字节,2个字节表示一个汉字。
GBK
Unicode编码体系:UTF-8,收录了常见语言的常见字符。3个字节表示一个字符。又叫万国码表。
Java的默认编码是UTF-8。
所有的码表全部兼容西欧码表,所以前256位全都只占1个字节。
2>转义字符
转义字符:\,基本所有的编程语言中\都是转义字符。
\’ 单引号 \\ 反斜杠 \” 双引号 \t 制表符 \r-return回车符 \n---newLine 换行符。
从JDK1.7开始,\r和\n功能一致。
3.布尔型
1>boolean
true/false 大小现在没做限定。大小根据操作系统和JDK版本不同而定。默认值是false。
boolean b = true;
2、引用数据类型(略)
1.分类
类:class,接口:interface,数组:[],原生类Arrays,枚举。
3、数据类型的转换
1.隐式类型转换
隐式类型转换又叫做自动类型转换。
整转小,小转大。
byte b = 10;
int i = b;
规律一:小类型可以自动转化为大类型。
float f = 4.2f
double d = f;
int i = 10;
float f = i;
规律二:整数可以自动的转化为小数,可能会出现精度损失问题。
long l = 9L;
float f = l;
float f = -25;//true
float f = 25.0; //false
char c = '大';
int i = c;
double = i;
规律三:char可以自动转化为int。
char c = '大';
int i = c;
long l = c;
double = i;
char c = 98;//true
short s= 'b';//true
char c='b';
short s= c;//false
因为两句话是分开编译的,所以范围无法确定。
char c =-1;//编译报错
隐式转换的规律可以用下图表示:
char c = 98;//---可以
short s = 'g';//---可以
char c = 98;
short s = c;
在代码编译期间,JVM会检查数据的类型和声明的类名是否一致或者兼容。如果在赋值的时候数据是一个变量,不会去检查这个变量的值而是检查变量的类型和声明的数据类型是否兼容。
float f = 30;//---true
float f = 30.0f;
long l = '中';//---true
long l = 100;//---true---如果一个整数在int的取值范围内,可以不用添加L作为结尾
2.显式类型转换
显式类型转换又叫做强制类型转换。
如果大类型赋值给一个小类型或者是把一个小数赋值给一个整数的时候就要使用显式转换。
当把大类型的转换为小的类型的时候,需要强制转换。
当把浮点型数据转换为整型变量的时候,需要强制类型的转换。小数转换成整数的时候,不是四舍五入,而是舍弃掉小数部分,因此,小数转换整数的时候,也会产生精度损失。
int i = 10;
byte b = (byte)i;
double d = 3.99;
int i = (int)d; //-> 3 -> 小数在强制转换为整数的时候会舍弃所有的小数位。
int i = 200;
byte b = (byte)i;//---可以
注意:在计算机中,绝大部分小数是没有办法精确表示的。
四、运算符
分六类:算数运算符、赋值运算符、比较/关系运算符、逻辑运算符、位运算符、三元/三目/条件运算符。
1、算术运算符
七个运算符:+加、-减、*乘、/除、%取模、++自增、--自减、+字符串拼接。
Java是一门强类型的语言,对每种数据类型都严格划分了数据类型。
int i =4350/1000*1000; //i结果为4000
//两个int类型参与运算,结果也是int类型。
1.规则
1. byte/short在运算的时候会自动的提升为int,然后进行运算,运算结果为int。
2. 同一个类型参与运算,结果的类型与参与运算的类型一致。
这里有个点就是int之前的类型,在参加运算的时候会转为int类型,所以是两个int类型参加运算,结果为int类型,没错,和第一条不冲突。
3. 如果运算过程中有大类型参与了运算,结果一定是大类型。
4. 由于绝大部分小数在转化成二进制的时候是无限小数,所以double类型在存储小数的时候也没有办法精确存储,因此也没有办法来精确运算。
5. 整数/0 :ArithmeticException(算数异常)。
任意非0数字/0.0或者是任意小数/0 结果为Infinity(无穷大)。
0/0.0结果为NaN-> Not a Number(非数字)NaN和任何值都不相等包括其本身。
判断一个对象是否是NaN只有一个方法isNaN();。
2.%(取模运算/取余)
5 % 3 = 2 1 % 4 = 1 -8%3=-2 8%-3=2 -8%-3=-2
确定结果符号:
在做取余运算的时候,先按正数进行取余,然后看%左边数字的符号,如果%左边的数字是正数,那么结果就是正数,反之则为负。
例如:
3.2 % 2 = 1.2 5.4%1.7=0.3 -3.5%1.7=-0.1
3.++/--
相当于在原来的基础之上自增/自减1。
++ 在变量名之前,表示先自增,自增完成之后才会参与其他运算。
++ 在变量名之后,表示先拿变量的原来的值参与运算,然后再自增。
例如:
int i = 5;
//int j = ++i; -> i = i + 1; -> int j = i; -> j = 6;
int j = ++i * 2;// -> i = 6, j = 12;
int i = 5;
// int j = i++; -> 表示先把5拿出来,i自增为6,然后把5赋值给j
int j = i++ * 2; -> i = 6, j = 10;//->先把i的值5取出来参与乘法运算,然后i自增
int i = 3;
// int j = i++ + ++i; -> i = 5, j = 8;
int j = ++i + i++; //-> i = 5, j = 8
注意:byte/short类型可以参与++/--运算,而且运算完成之后依然是原来的类型,Java在底层已经进行了强制转换。
byte b=127;
b++;//值为-128
4.+字符串拼接
“a”+”b” --->”ab” 2+3+”a”--->”5a”
String s = "a";
s = s + "b"; //-> s = “ab”
可以利用+将两个字符串进行拼接,或者也可以利用+将任何数据与字符串进行拼接。
2、赋值运算符
十二个运算符:=(等于)、+=(加等)、-=(减等)、*=(乘等)、/=(除等)、%=(取余等) 、&=(与等)、|=(或等)、^=(异或等)、<<=(左移等)、>>=(右移等)、>>>=(无符号右移等)。
注意:除了=以外,其余的赋值运算符要求这个变量必须有初始值。
byte/short可以参与赋值运算,运算结果仍是原类型。
例如:
byte b =25;
b += 5;
int i = 5;
i += i -= i *= 3;// --->-5
i += i -= i *= i++;// ---> i = -15
i+= i -= i *= i ++ * 2;//--->i=-40
i = 5+ (5 - ( 5 * 5));
3、关系运算符
关系运算符又叫比较运算符。
七个运算符:==等于、!= 不等于、>(大于) 、<(小于)、>=(大于等于)、<=(小于等于)、instanceof(判断对象于实例的关系)。
int i = 4;
int j = 5;
i == j; //-> false
i != j; //-> true
i > j; //-> false
1.instanceof
用于判断对象是否是否对应类的实例的。
"abc" instanceof String; //-> true
运算完成之后结果是一个boolean类型的值。
4、逻辑运算符
六个运算符:&与(And)、|或(Or)、!非(Not)、^异或、&&短路与、||短路或。
1.&运算规则:
true&true=true;
true&false=false;
false&true=false;
false&false=false;
见false为false。
2.|运算规则:
true|true=true;
true|false=true;
false|true=true;
false|false=false;
见true为true。
3.!运算规则:
!true=false;
!false=true;
非否即是,非是即否。
4.^运算规则:
true^true=false;
true^false=true;
false^true=true;
false^false=false;
相同则为false,不同则为true。
5.&&运算规则:
对于&&而言,如果前边的表达式的结果为false,则后边的表达式就不再运算。
6.||运算规则:
对于||而言,如果前边的表达式的结果为true,则后边的表达式就不再运算。
int i = 3,j = 4,k = 5;
boolean b = i > j && k++ > 3||i++ > 2;
System.out.println(i);
System.out.println(j);
System.out.println(k);
注意:短路特性可以提高代码的运算速度。
5、位运算符
7个运算符号:
&(与)、|(或)、 ^(异或)、<<(左移)、>>(右移)、>>>(无符号右移)、~(取反)。
注意:位运算针对的是整数,运算的是数据的补码。可以利用&来判断是否是奇偶数。
1.原、反、补码
数据在计算机中是以补码形式来存储的。最高位是一个符号位:如果是正数,最高位为0,如果是负数,最高位为1。对于正数而言,原反补三码一致。负数的反码是在原码的基础上,最高位不变,其余位0变1,1变0,负数的补码是在反码的基础上+1。
6- 00000000 00000000 00000000 00000110---原码/反码/补码
-6 - 10000000 00000000 00000000 00000110---原码
11111111 11111111 11111111 11111001---反码
11111111 11111111 11111111 11111010---补码
11111111 11111111 11111111 11101101---补码
11111111 11111111 11111111 11101100---反码
10000000 00000000 00000000 00010011---原码--- -19
2.与或非运算规则
奇数^偶数=奇数
a ^ b ^ b = a;
b ^ b ^ a = a;
1>交换两个数的值
int i = 3, j = 5;
方式一:第三方变量(常用)
int k = i;
i = j;
j = k;
方式二:加减法
i = i + j;
j = i - j;
i = i - j;
//简化形式
i+=j;j=i-j;i-=j;
方式三:异或(效率更高)只针对整数运算。
i = i ^ j;
j = i ^ j; //----> j = i ^ j ^ j; -> j = i;
i = i ^ j; //----> i = i ^ j ^ i; -> i = j;
//简化形式
i ^= j; j ^= i; i ^= j;
3.位移运算规则
注意:
Java中所有的数值类型的数据都是有符号的。
baty/short参加左移和右移和无符号右移结果为int。
一个数字右移几位就是将这个数字除以2的几次方,然后取整。
取反快捷运算:~i= - i - 1
6、三元运算符
三元运算符又叫三目运算符,还可叫做条件运算符。
1.格式
逻辑值 ? 表达式1 :表达式2;
例如:
int i = 4, j = 7;
int k = i > j ? i : j;
System.out.println(k);//结果为j。
2.执行顺序:
如果逻辑值为true的话,执行表达式1,;反之执行表达式2。
①三元表达式在运算完成之后必须有一个结果。
//不允许,运算完成之后,没有结果。
A > b ? System.out.println( a ) : System.out.println( b );
②表达式1和表达式2的结果必须是相同类型或相容。
double d = a > b ? a * 2 : a * 2.5;
③在三元表达式形成嵌套的时候,尽量添加()来提高代码的可读性
int max = a > b ? ( a > c ? a : c ) : ( b > c ? b : c );
面试题
下面的代码有什么问题?
int i = 3 , j = 4;
System.out.println( i > j ? true : false );
语法上没有什么问题, i > j ? true : false和i < j 的结果是一样的,在代码上造成了冗余。
练习
判断是否是一个奇数?
int i=10;
boolean bo =i%2==0;
成绩>=90,显示输出A;成绩>= 80,显示输出B;成绩>= 60,显示输出C;成绩< 60,显示输出D。
可以自己练习以下这道题。
8、运算优先级
大体上是先进行一元运算,然后是二元运算,再是三元运算,最后是=。
一元运算:!、++/--、~、
二元运算:算数、比较、逻辑、位。
个人总结的大体优先级如下:
()、!、++/--、~、算数(*、/、%、+、-)、比较、逻辑(先或后与)、位(<<、>>、>>>、&、|、^)三元、赋值。
五、流程控制
1、顺序结构
是指代码是从上到下从左到右依次运行的。
2、分支结构
分支结构分为判断结构和选择结构。
1.判断结构
1>if
格式:if( 逻辑值 ){ code;}
如果逻辑值为true,执行对应的代码块,反之则不执行。
注意:if后面的{}。只有一句代码的时候可以省略。
代码示例:
import java.util.Scanner;//导包语句,位置要在class之外。
public class IfDemo {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
int i = s.nextInt();
if(i > 10){//if语句
System.out.println("hahah~~~");
}
}
}
练习:判断三个数中的最大数。
这是一个经典练习,可以自己做一下。
2>if-else
格式:if(逻辑值){Code1;} else {Code2;}
如果逻辑值为true,执行Code1;反之执行Code2。
//判断奇偶
import java.util.Scanner;
public class IfElseDemo {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
int i = s.nextInt();
if(i % 2 == 1){
System.out.println(i + "is an odd number .");
} else {
System.out.println(i + "is an even number .");
}
}
}
练习
输入三个数,获取最大值
import java.util.Scanner;
public class Test1{
public static void main(String[] args){
Scanner s=new Scanner(System.in);
int num1=s.nextInt();
int num2=s.nextInt();
int num3=s.nextInt();
int max;
if(num1>num2){
if(num1>num3){
max=num1;
}else{
max=num3;
}
}else{
if(num2>num3){
max=num2;
}else{
max=num3;
}
}
System.out.println(max+" is max.");
}
}
3>If-else if-else
格式:
if(逻辑值1){
Code1;
} else if(逻辑值2){
Code2;
}...else {
Code;
}
如果逻辑值1为true,执行Code1;如果逻辑值1为false,则判断逻辑值2是否为true,如果逻辑值2是true,则执行Code2。
import java.util.Scanner;
public class IfElseIfDemo {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
double score = s.nextDouble();
If(score > 100||scpre < 0){
System.out.println(erres);
}else if(score >= 90){
System.out.println("A");
} else if(score >= 80 ){
System.out.println("B");
} else if(score >= 60){
System.out.println("C");
} else {
System.out.println("D");
}
}
}
练习
输入一个月份,输出月份对应的季节 3-5-Spring 6-8-Summer 9-11-Autumn 12-2-Winter
import java.util.Scanner;
public class Test2{
public static void main(String[] args){
Scanner s=new Scanner(System.in);
int month=s.nextInt();
String season = "";
if(month>=13||month<=0){
season ="Wrong month !";
}else if(month>=3&&month<=5){
season ="Spring";
}else if(month>=6&&month<=8){
season = "Summer";
}else if(month>=9&&month<=11){
season ="Autumn";
}else{
season ="Winter";
}
System.out.println(season);
}
}
2.选择结构
1>Switch
格式
switch(表达式){
case 选项1: code1; break;
case 选项2: code2; break;
……
default: code;break;
}
注意
表达式的值只能是byte/short/char/int四种类型,JDK1.7开始,支持对String进行选择,从JDK1.5开始允许表达式的结果是枚举常量。
break对多行case代码有影响。
如果case之后没有break,那么从匹配的case开始,依次往下执行,直到遇到break或者是switch语句结束。
如果每个case之后都有break的话,case之间的顺序不影响最后的结果;即使有一个case没有break,这个时候case之间的顺序会影响最后的结果。
明坑题
int i = s.nextInt();
// int j ;
switch(i){
case 1 : int j = 0;
case 2 : j += 1; // 编译报错 可能尚未声明变量j
case 3: j += 3;
default : System.out.println(j);
}
练习
计算器一个符号和两个数字 - 5 9-> 5 - 9 = -4
import java.util.Scanner;
public class SwitchCaseExer {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
String symbol = s.nextLine();
int i = s.nextInt();
int j = s.nextInt();
switch(symbol){
case "+" :
System.out.println(i + j);
break;
case "-" :
System.out.println(i - j);
break;
case "*" :
System.out.println(i * j);
break;
case "/" :
System.out.println(i / j);
break;
default:
System.out.println("No this operation !");
}
}
}
3、循环结构
三个要素:循环变量,循环条件,变量改变。
尽量不要使用浮点型来作为循环条件,因为小数在计算机中不能够精确存储。
1.while
1>格式
while(判断循环变量){
code;
}
2>执行逻辑
public class WhileDemo {
public static void main(String[] args){
int i = 1;
while(i <= 5){
System.out.println("Hello");
i++;
}
}
}
练习
从控制台输入一个数字,求1-这个数字的和
import java.util.Scanner;
public class WhileExer1 {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
int n = s.nextInt();
/*
int i = 1;
int sum = 0;
while(i <= n){
sum = sum + i;
i++;
}
*/
int sum = 0;
while(n > 0){
sum += n;
n--;
}
System.out.println(sum);
}
}
输出500以内8的倍数
int i = 0;
while(i <= 500){
System.out.println(i);
i += 8;
}
/*
while(i <= 500){
if(i % 8 == 0){
System.out.println(i);
}
i++;
}
*/
输入一个数字,输出这个数字是几位数---3463-4
Scanner s = new Scanner(System.in);
int number = s.nextInt();
int i = 0;
while(number != 0){
number /= 10;
i++;
}
System.out.println(i);
输入一个数字,输出各位数字之和--- 3463 - 16
Scanner s = new Scanner(System.in);
int number = s.nextInt();
int sum = 0;
while(number != 0){
sum += (number % 10);
number /= 10;
}
System.out.println(sum);
输入一个数字,输出这个数的二进制。
Scanner s=new Scanner(System.in);
int num =s.nextInt();
String str="";
while(num!=0){
str= num % 2 + s;
num/=2;
}
System.out.println(str);
求PI的计算次数
public static void main(String[] args) {
int i=0;
int base =1;
double PI = 0;
double sign =1.0;
while(PI >3.1415927 || PI < 3.1415926){
PI = PI + 4 * sign/ base;
i++;
sign *= -1;
base += 2;
}
System.out.println(i);
}
2.do-whlie
1>格式
do{
Code;
}while(逻辑值);
2>执行逻辑
int i = 20;
/*
while(i <= 10){
System.out.println(i);
i++;
}
*/
do{
System.out.println(i);
i++;
}while(i <= 10);
注意:do--whlie循环中代码块至少执行一次。
3.for
1>格式
for(定义循环变量;循环条件的判断;循环变量的改变){
Code;
}
2>执行逻辑
当循环变量改变相对比较规律的时候,建议使用for循环。
当不知道循环次数的时候,建议使用while。
While循环,循环变量定义在循环外,循环结束之后循环变量依然可以使用;for循环的循环变量是定义在for循环里边的,循环结束之后,循环变量不能继续使用。
for(int i = 1; i <= 5; i++){
System.out.println("Hello");
}
*/
int sum = 0;
for(int i = 1; i <= 100; i++){
sum += i;
}
练习
求一个数二进制的1的个数。
一个int 类型的整数由32 个二进制位组成,每个二进制位的值要么为0 要么为1。要求读入一个int 类型的整数n,计算它的32 个二进制位中总共有多少位为1?
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
int number =s.nextInt();
s.close();
int j=0;
for (int i = 0; i < 32; i++) {
if((number &1)==1){
j++;
}
number >>=1;
}
System.out.println(j);
}
4.循环的嵌套
循环结构中包含了其他的循环结构,形成了循环的嵌套。
循环嵌套可以实现也下功能:
public class ForDemo2 {
public static void main(String[] args){
/*
*****
*****
*****
*****
*/
for(int j = 1; j <= 4; j++){
for(int i = 1; i <= 5; i++){
System.out.print("*");
}
System.out.println();
}
/*
*
**
***
****
*****
row: 1 -> 5
*: 1 -> i
*/
for(int i = 1; i <= 5; i++){
for(int j = 1; j <= i; j++){
System.out.print("*");
}
System.out.println();
}
/*
*****
****
***
**
*
*/
for(int i = 5; i > 0; i--){
for(int j = i ; j > 0; j--){
System.out.print("*");
}
System.out.println();
}
/*
----*
---**
--***
-****
*****
row:1-5
" ": 1 -> 5 - i
*: 1 -> i
*/
for(int i = 1; i <= 5; i++){
for(int j = 1; j <= 5 - i; j++){
System.out.print(" ");
}
for(int j = 1; j <= i; j++){
System.out.print("*");
}
System.out.println();
}
/*
*****
****
***
**
*
row:5 -> 1
" ": 5 - i -> 1
* : i -> 1
*/
for(int i = 5; i > 0; i--){
for(int j = 5 - i; j > 0; j--){
System.out.print(" ");
}
for(int j = i; j > 0; j--){
System.out.print("*");
}
System.out.println();
}
}
}
练习
九九乘法表
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
for(int i = 1; i <= 9; i++){
for(int j = 1; j <= i; j++){
System.out.print(j + "*" + i + "=" + i * j + "\t");
}
System.out.println();
}
百钱买百鸡
3 文钱可以买1只公鸡,2 文钱可以买一只母鸡,1 文钱可以买3 只小鸡。用100 文
钱买100 只鸡,那么各有公鸡、母鸡、小鸡多少只?
水仙花数
所谓水仙花数,是指一个三位数abc,如果满足a3+b3+c3=abc,则abc 是水仙花数。(善用%)
5.break和continue
1>break
作用于选择结构和循环结构,表示终止当前的一层语句。
2>continue
只能作用于循环结构,表示跳出当前的一次循环继续下次循环。
这两个关键字必须结合相应的语句使用个,单独存在没有意义,因此单独存在的时候编译报错。
Java中,不允许废话存在,存在废话就会编译报错。
3>循环标号
Java中支持对循环进行标号。
当需要一次性跳出多层循环的时候,可以使用标号形式,但是不推荐使用,因为降低了程序的阅读性。
A:for(int i = 0 ; i < 3; i++){ //A为标号
B:for(int j = 0; j < 4; j++){
for(int k = 1; k < 6; k++){
if(k == 3){
break A;
}
If(k==1)
continue B;
System.out.println(i + "," + j + "," + k);
}
}
}
练习
判断质数
一个数除了1和本身不能整除其他的数。(使用Math.sqrt()注意2和3的判断。)
分解质因数
100 = 2 * 2 * 5 * 5; 18 = 2 * 3 * 3;
import java.util.Scanner;
public class Exer{
public static void main(String[] args){
Scanner s=new Scanner(System.in);
int number = s.nextInt();
while(number!=1){
for(int i=2;i<=number;i++){
if(number%i==0){
System.out.println(i);
numbber/=i;
break;
}
}
}
}
}
六、数组(Array)
分为一维数组和二维数组。
1、一维数组
1.定义
存储一组同一个类型数据的容器叫做数组。
数组对每一个存入的数字都会自动编号,编号是从0开始的,这个编号叫下标。
2.格式
声明数组的格式有三种。
1.数据类型[] 数组名 = new 数据类型[表示数组能存放的元素个数];
适用于一些知道元素个数而不知道具体元素的场景。
int[] arr = new int[5]; 表示定义了一个能存储5个int类型的数据的数组。
int arr[];//允许先声明,再初始化。
arr = new int[3];
int[] arr1 = new int[5];
arr[2] = 15; int i = arr[2];
System.out.println(arr[2]);
2.数据类型[] 数组名 = new 数据类型[]{元素1, 元素2,……,元素n};
同时也就规定了数组的大小就是元素的个数。
int[] arr = new int[]{3,5,1,2,5};
int[] arr1;//允许先声明再初始化。
arr1 = new int[]{3,5,1,2,4,7}
arr[3] = 10;
注意:数组一旦定义好,大小不可变
3.数据类型[] 数组名 = {元素1, 元素2,……,元素n};
int[] arr = {2,6,4,7,9};
3.内存
这里有必要先提一下,java JVM的内存。
Java将内存分为了五块:栈内存,堆内存,方法区,本地方法栈,寄存器。
注意:内存的初始化过程在程序之前,内存在初始化完成之后才会赋值。
对于基本类型而言,传值传的是实际值,对于引用类型而言传值传的是地址。
1>栈内存
存储变量,执行代码块的。
①变量是存储在栈内存中的。
②变量在栈内存中用完之后立即移除,释放内存空间,提高内存的利用率。
③变量在栈内存中不会自动赋予默认值。
2>堆内存
存储对象。对象在堆内存中会自动的赋予一个默认值。对象在使用完成之后,不会立即移除,而是在不定的某个时刻被回收。
①默认值
byte/short/int 默认值是0。
long 的默认值是0L。
float的默认值是0.0f。
double的默认值是0.0。
char 的默认值是‘\u0000’。
boolean 的默认值是false。
所有的引用类型的默认值全部都是null。
3>栈堆关系
ArrayIndexOutBoundsException :数组下标越界异常。
编译没有问题,说明语法没有问题,逻辑上或者事实上不符合,才会运行报错。
NullPointerException :空指针异常。
4.数组的应用
1>获取指定位置上的元素
数组名[下标]:arr[n];。
2>获取数组的长度
数组名.length:arr.length;。
3>遍历数组(ergodic array)
①普通for循环
for(int i = 0;i < arr.length; i ++){
System.out.println(arr[i]);
}
②增强for循环
1.增强for循环是基于迭代器。
2.无法改变原来数组的元素。
// 表示把数组中的元素依次取出赋值给i
for(int i : arr){
System.out.println(i);
}
for(String s : arr){
System.out.println(s);
}
③Arrays.toString();
将数组中的元素依次取出,拼接成一个字符串。
String str = Arrays.toString(arr);
System.out.println(Arrays.toString(arr));
4>获取数组元素的最值。
获取最大值用遍历数组。
①增强for循环
int max = arr[0];
for(int i : arr){
if(max < i){
max = i;
}
}
System.out.println(max);
②普通for循环
int max = 0;
for(int i = 0; i < arr.length; i++){
if(arr[i] > arr[max]){
max = i;
}
}
System.out.println(arr[max]);
5>数组元素排序
数组元素排序有冒泡排序、选择排序、快速排序、希尔排序、堆排序等多种排序方法。
①冒泡排序
方法如下:
for(int i = 1; i <= arr.length - 1; i++){
for(int j = 1 ; j <= arr.length - i; j++){
if(arr[j - 1] > arr[j]){
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
②选择排序
这个方法我还没有整理出来,后期整理出来,会补上的。
③Arrays.sort()
需要导包语句,只能从小到大排序。
import java.util.Arrays;
Arrays.sort(arr);
6>查找元素的位置
①遍历
针对无序数组。
class MyClass{
public static void main(String[] args){
int[] arr={5,6,2,4,8,1,3,7};
int a = 4;
int index = -1;
for(int i=0;i < arr.length;i++){
if(arr[i]==a){
index = i;
break;
}
}
System.out.println(index);
}
}
②折半查找(掌握)
针对有序数组。时间复杂度:O(log2n)
class MyClass{
public static void main(String[] args) {
int[] a={1,3,4,6,8,9,15,19,25,36,48};
int num=25;
int min=0;
int max=a.length-1;
int mid=(min+max)/2;
boolean b=true;
while(min<=max){
if(num==a[mid]){
System.out.println(mid);
b =false;
break;
}else if(num>a[mid]){
min=mid+1;
}else if(num<a[mid]){
max=mid-1;
}
mid=(min+max)/2;
}
if(b)
System.out.println("no");
}
}
7>反转数组
头尾交换数组的元素。
方法一:利用第三方数组。
方法二:利用两个变量同时操作数组的两端。
int[] arr = {12,15,26,38,49,80,91};
for(int start = 0, end = arr.length - 1; start < end ;start++,end--){
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
System.out.println(Arrays.toString(arr));
注意:如果访问的下标不存在,会出现ArrayIndexOutOfBoundsException---数组下标越界异常---编译的时候没有报错---因为语法无错。---所以编译检查的是语法问题。
8>数组的扩容/复制
实际上是产生了一个新的数组。
①System.arraycopy()
System.arraycopy(要复制的数组, 要复制的起始下标, 要存放的数组, 存放的起始位置, 复制的元素的个数);
System.arraycopy(arr,3,arr1,2,4);
//从arr中3的位置开始复制,存放到arr1中,从arr1中2的位置开始存放,复制4个元素。
int arr ={1,2,3,4,5};
int arr1=new int[arr.length * 2];
System.arraycopy(arr,0,arr1,0,arr.length);
arr=arr1;
②Arrays.copyOf()
arr=Arrays.copyOf(要扩容的数组, 扩容之后的大小);
数组在扩容完成之后,堆内存的地址已经发生了改变,底层使用的就是System.arraycopy();。
Arrays.copyOf(arr,len);//底层代码。
int[] arr={1,2,3,4}
int[] arr2 = new int[len];
if(len < arr.length){
System.arraycopy(arr,0,arr2,0,len);
} else {
System.arraycopy(arr,0,arr2,0,arr.length);
}
arr = arr2;
2、二维数组
1.定义
二维数组的每一个元素就是一个一维数组,是一个存放数组的容器。实际上二维数组中存储的是一维数组在堆内存中一维数组的内存地址。
2.格式
声明二维数组的格式也有三种。
1.数据类型[][] 数组名 = new 数据类型[二维数组的大小][一维数组的大小];
int[][] arr = new int[3][5];
表示定义了一个包含了3个一维数组的二维数组,每个一维数组包含5个整数元素。
arr[1][3] = 5;//赋值
int[]arr[] = new int[3][5];
int arr[][] = new int[3][5];
int[] arr2 = arr[0];//--获取的是一个一维数组。
arr[0][2];// ---获取具体的元素,需要两个下标。
2.数据类型[][] 数组名 = new 数据类型[二维数组的大小][];
int[][] arr = new int[5][];//---表示二维数组中包含5个一维数组。
int[][] arr =new int[5][];
//给每个一维数组规定长度。
arr[0] = new int[5];
arr[1] = new int[3];
arr[2] = new int[0];
arr[3][0] = 8;//---NullPointerException---空指针异常
注意:针对null的任何操作都会出现空指针异常
3.数据类型[][] 数组名 = {{元素1,元素12,……},{元素21,元素22,……},……{}};
int[][] arr = {{2,3}, {1}, {3,5,6}, {1,2,3,7}, {1}};
笔试题总结:
对于数组int[] x, y[]均已初始化,下面各项正确的是:--- BC --- y[][] x[]
A. y[0] = x[0];
B. y[0] = x;//一维数组赋值给二维数组。
C. y[0][0] = x[0];//一维数组的具体值,赋值给二维数组的具体元素。
D. y[0][0] = x;
E. y[0] = x[0][0];
注意:[]在变量名之前紧跟的是数据类型,以后定义的每一个变量都会拥有这个[];如果[]在变量名之后,那么[]只属于当前的变量。
3.应用:
2>二维数组的长度
数组名.lenght。 arr.length 每个一维数组:数组名[下标].lengyh。 arr[0].length
3>遍历
遍历二维数组需要两层循环。
①双层for循环。
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
System.out.println(arr[i][j]);
}
}
②Arrays.toString();
输出的是二维数组中存储的一维数组的地址。
4>二维数组的反转
二维数组里面的各个一维数组头尾交换位置。
for(int statt = 0,end = arr.length - 1; start < end ; start++,end--){
int temp[] = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
练习:
杨辉三角(二维数组)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
输入一个数n,输出前n行
//从控制台获取行数
Scanner s = new Scanner(System.in);
int row = s.nextInt();
//根据行数定义好二维数组,由于每一行的元素个数不同,所以不定义每一行的个数
int[][] arr = new int[row][];
//遍历二维数组
for(int i = 0; i < row; i++){
//初始化每一行的这个一维数组
arr[i] = new int[i + 1];
//遍历这个一维数组,添加元素
for(int j = 0; j <= i; j++){
//每一列的开头和结尾元素为1,开头的时候,j=0,结尾的时候,j=i
if(j == 0 || j == i){
arr[i][j] = 1;
} else {//每一个元素是它上一行的元素和斜对角元素之和
arr[i][j] = arr[i -1][j] + arr[i - 1][j - 1];
}
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
七、方法(method)
1、定义
将一段逻辑或者功能提取出来,这种提取的形式就是方法,也叫函数。
为了实现某段代码的重复利用,将这段代码进行封装,这种封装的形式就是方法,也叫函数。
2、格式
修饰符 返回值类型 方法名(参数列表){
方法体;
return 返回值;
}
声明方法要注意两点:
1.明确返回值类型。方法执行完成之后,返回值的数据类型是什么方法的返回值类型就是对应的类型。
例如:求整型数组的元素之和,确定返回值类型是int。
2.明确是否需要参数。如果方法执行过程中需要一些未知量参与运算,而未知量在方法中不能自动产生,那么这个时候需要以参数的形式体现。
声明一个参数实际上就是声明了变量,形式参数,也叫形参。
// 方法签名---add(int[])
public static int add(int[] arr){
int sum = 0;
for(int i : arr){
sum += i;
}
return sum;
}
在调用函数传入的实际值叫实际参数,也叫实参。
add(arr);
1.注意:
1.如果方法执行完成之后没有返回值,那么返回值类型就是void。
2.return之后的代码就执行不到了,一个函数一旦return,那么后续代码就不再执行了。
3.任何一个实体方法内都可以写return语句。
3、方法的重载
1.定义
当同一个类内出现了方法名一致而参数列表不同的方法的时候,构成了方法的重载。
方法名一致而参数列表不同,方法名+参数列表叫做方法签名,和修饰符、返回值类型、异常等无关,是一种编译时多态。
public static int add(int i,int j){ code }
public static double add(int i ,double d){ code }
public static double add(double d,int i){code}
public static int add(int i,int j,int k){ code }
方法在调用的时候会进行最优匹配。找参数类型最符合的进行匹配。
如果进行方法的重载,尽量重载所有的情况,以防出现调用混乱的情况。
4、方法的重写
1.定义
当父子类中产生了方法签名完全一致的非静态方法的时候,构成了方法的重写/覆盖。
重写的标志注解:@Override。
2.规则
注意:方法的重写需要遵循 “两等两小一大”
1.父子类中方法签名必须一致。
方法重写的前提,父子类中可以出现方法名称一样签名不一样的方法。
2.如果父类中方法的返回值类型是基本类型/void/最终类,那么子类重写的方法的返回值类型必须一致。
注意:八种基本类型之间没有继承关系。
class A {
public void m(){}
}
class B extends A {
public void m(){}
}
3.如果父类方法的返回值类型是引用数据类型,那么子类重写的方法的返回值类型是父类方法返回值类型的子类或者是本身。
Class A{
Public void m(){}
}
Class B extends A{
Public void m(){}
Public void mb(){}
}
Class C{
Public B mc(){return new B();}
}
Class D extends C{
Public A mc(){return new A ();}
//D类的mc方法没有C类的大,如果使用向上造型创建C类对象,使用会有范围的冲突。B类的东西比A类多有写东西实现不了。
}
4.子类重写的方法的编译时异常必须是父类方法异常的子类或者本身。子类不能抛出比父类更多的异常,范围不能更大,而且指的是编译时异常。对于运行时异常不做限定。
5.子类重写的方法的权限修饰符的范围必须大于等于父类。
class A{
public void m(){}
}
class B extends A {
private void m(){}
}
A a = new B();
// a对象使用A类来声明的,A类告诉a对象身上有一个m方法,而且这个m方法是用public修饰的;
//等到具体使用的时候要看子类,子类是用B类来创建的,
//使用的时候发现B类中把这个方法声明为了private。产生了范围冲突。
5、方法重写和重载的异同
方法的重载和重写都是一种行为多态。
重载是指在同一个类中存在来方法名一致而参数列表不同的方法的现象。方法的重载只和参数列表中对应位置参数的参数类型是否一致有关,和其他的元素无关;方法的重载是一种编译时多态。
重写是指在父子类中存在来方法签名完全一致的方法的现象。方法的重写是基于继承和实现存在的。方法的重写要求方法签名必须一致;在重写的过程中,如果父类方法的返回值类型是基本类型、void、最终列的时候,那么子列对应方法的返回值类型要一致;如果父类方法的返回值类型是其他引用类型,这个时候子类对应方法的返回值类型要是父类方法返回值类型的子类或者是本身。在重写过程中,如果父类方法抛出来异常并且该异常是编译时异常的时候,子类重写的方法可以不抛出异常,或者是在父类编译时异常的范围下抛出,而对于运行时异常没有限制。在重写的过程中,要求子类方法的权限修饰符要大于等于父类。重写本身是一个运行时多态。所以对于静态方法而言不存在重写,但是父子类中允许存在方法签名一致的静态方法。
6、方法的递归
1.定义
函数调用自己本身就形成了递归。
//从1+到number的和。
public static int sum(int number){
if(number <= 0){
return 0;
}
return number + sum(--number );//函数调用自己本身。
}
练习
1>用递归求阶乘
public static long factorial(int number){
if(number == 0){
return 1;
}
return number * factorial( -- number);
}
递归的效率会低一些。
控制好结束条件,如果递归层数太深,会出现栈溢出错误(StackOverFlowError)。
StackOverFlowError :栈溢出错误,说明方法/函数在栈内存中执行。
注意:在传递参数的时候,对于基本类型而言,传递的实际值;对于引用类型而言,传递的是地址。只要地址不发生改变,函数中一切变化会作用于原数组。
7、作用
1.提高代码的复用性。
2.代码的结构更加清晰。
3.便于模块化(团队)开发
练习
判断质数(prime)
import java.util.Scanner;
public class MethodExer1 {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
int number = s.nextInt();
boolean b = isPrime(number);
System.out.println(b);
}
public static boolean isPrime(int number){
if(number <= 1){
return false;
}
for(int i = 2; i <= number / 2; i++){
if(number % i == 0){
return false;
}
}
return true;
}
}
2.亲密数
A的所有因子(包含了1而不包含本身)之和等于B,并且B的所有因子(包含1而不包含本身)之和等于A,那么A和B就是一对亲密数。1000以内。
public class MethodExer2 {
public static void main(String[] args){
for(int i = 1; i <= 5000; i++){
int b = sumAllFact(i);
int c = sumAllFact(b);
if(c == i && i < b){
System.out.println(i + "," + b);
}
}
}
public static int sumAllFact(int number){
int sum = 0;
for(int i = 1; i <= number / 2; i++){
if(number % i == 0){
sum += i;
}
}
return sum;
}
}
3.任何一个大于等于6的偶数都可以分解为两个质数之和。
6= 3 + 3; 14 = 3 + 11 = 7 + 7 18 = 5 + 13 = 7 + 11
import java.util.Scanner;
public class MethodExer3 {
public static void main(String[] args){
Scanner s = new Scanner(System.in);
int number = s.nextInt();
while(number < 6 || number % 2 == 1){
number = s.nextInt();
}
for(int i = 3; i <= number / 2; i+=2){
if(isPrime(i) && isPrime(number - i)){
System.out.println(number + "=" + i + "+" + (number - i));
}
}
}
public static boolean isPrime(int number){
for(int i = 2; i <= number / 2; i++){
if(number % i == 0){
return false;
}
}
return true;
}
}
以上内容为个人学习整理,如果错误,请大家批评斧正!