Java基础
java语言平台版本
Java SE(Java Paltform Standard Edition)标准版
1、是为开发普通桌面和商务应用程序提供的解决方案
2、该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发
Java ME(Java Platform Micro Edition)小型版
是为开发电子消费产品和嵌入式设备提供的解决方案
Java EE(Java Platform Enterprise Edition)企业版
1、是为开发企业环境下的应用程序提供的一套解决方案
2、该技术体系中包含的技术如Servlet、JSP等,主要针对WEB应用程序开发
java语言特点
1、简单性、面向对象、分布式处理、健壮性、结构中立、解释性、高性能、多线程、动态、安全性
2、开源、跨平台(重要)
跨平台性(可移植性):通过Java语言编写的应用程序在不同的系统平台上都可以运行
原理:只要在需要运行java应用程序的操作系统上,先安装一个java虚拟机(Java Virtual Machine )即可,由JVM来负责java程序在该系统中的运行
JDK、JRE、JVM
JDK(Java Development Kit):
JDK是提供给java开发人员使用的,其中包含了java的开发工具(编译工具javac.exe,打包工具jar.exe,java.exe),也包括了JRE,所以安装了JDK,就不用再单独安装JRE了,
JRE(Java Runtime Environment):
包括Java虚拟机和Java程序所需要的核心类库等,如果想要运行一个开发好的程序,计算机中只需要安装JRE即可
总结:使用JDK开发完成的java程序,交给JRE去运行,由JVM保证了跨平台性
JDK下载安装
下载官网:www.oracle.com
path配置环境变量
path环境变量的作用:在任意目录下都可以使用javac命令
新建JAVA_HOME环境变量为jdk安装的目录
在path环境变量中添加%JAVA_HOME%\bin
classpath环境变量配置
作用:让classpath变量中的class文件在任意目录下被执行
创建新的变量名称:classpath
值设定为指定的含有class文件的目录,多个目录间使用分号分割
通常将配置的目录最前面添加.配置,即当前目录,使class文件搜索时首先搜索当前目录,然后根据目录配置的顺序依次查找
path和classpath的区别
path变量中配置的是.exe文件,查找顺序是现在当前目录查找,然后再去path环境变量中查找
classpath变量配置的是class文件,在没有该环境变量时java会在当前目录查找,
一旦设置了该环境变量,java将按照配置的顺序依次查找,如果没有配置当前目录则不会查找当前目录,所以在配置的时候在最前面添加.(表示首先查找当前目录);
程序解析:
1、首先编写java源代码程序,扩展名.java
2、在命令行模式中,输入javac命令对源代码进行编译,生成字节码文件(类名.class)
3、编译完成后,如果没有报错信息,输入java命令对class字节码文件进行解释运行,不需要添加.class扩展名
关键字:
概述:被java语言赋予特定含义的单词
特点:组成关键字的字母全部小写
注意事项:
1、goto和const作为保留关键字存在,目前并不使用
2、类似Notepad++这样的高级记事本,针对关键字有特殊的颜色标记,非常直观
标识符:
概述:就是给类、接口、方法、变量等起名时使用的字符序列
组成规则:
1、英文大小写字母
2、数字符号
3、$和_
注意事项
1、不能以数字开头
2、不能是Java中的关键字
3、区分大小写
常见命名规则:见名知意
1、包:其实就是文件夹,用于把相同的类名进行区分,全部小写
单级:package
多级:package.first
2、类或者接口:
一个单词:单词的首字母必须大写,比如Student,Dog
多个单词:每个单词的首字母必须大写,比如HelloWorld,StudentName
3、方法或者变量:
一个单词:单词的字母都小写,比如name,age
多个单词:从第二个单词开始,每个单词的首字母大写,比如studentName
4、常量:
一个单词:全部大写,比如PI
多个单词:每个字母都大写,用_隔开,比如STUDENT_MAX_AGE
注释:
概述:用于解释说明程序的文字
java中注释分类格式
单行注释://注释文字
多行注释:/*注释文字*/,不能嵌套
文档注释:/**注释文字**/,被javadoc工具解析生成一个说明书
常量
概述:在程序执行的过程中其值不可以发生改变的量
java中的常量分类
1、字面值常量
1.字符串常量:用双引号括起来的内容
2.整数常量:所有整数
3.小数常量:所有小数
4.字符常量:用单引号括起来的内容
5.布尔常量:只有true和false
6.空常量:null
2.自定义常量(面向对象部分讲解)
java针对整数常量提供了4中表现形式
1.二进制,由0,1组成,以0b开头
2.八进制,由0~7组成,由0开头
3.十进制,由0~9组成,整数默认是十进制
4.十八进制,0~f(大小写均可),以0x开头
有符号数据表示法
1.在计算机内,有符号数有3中表示方法:原码、反码和补码。所有数据的运算都是采用补码进行的。
2.原码:就是二进制定点表示,即最高位为符号位,0表示正,1表示负,其余位数表示数值的大小
3.反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反(0变1,1变0),但符号位除外
4.补码:正数的补码与其原码相同;负数的补码是在其反码的末尾加1
变量
概述:在程序执行的过程中,其值是可以在一定范围内发生改变的量。
组成规则:
1.数据类型 变量名 = 初始化值;
2.数据类型 变量名;变量名 = 初始化值;
数据类型
java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间
分类:
1、基本数据类型(4类8种)
a.数值
1.整数类型
byte占1字节,-128~127
short占2字节,-2^15~2^15-1
int占4字节,-2^31~2^31-1
long占8字节,-2^63~2^63-1
2.浮点类型
float占4字节,-3.403E38~3.403E38
double占8字节,-1.798E308~1.798E308
说明:
1.整数默认int,小数默认double
2.定义长整型数据时,如果超过了int范围,则需要在数值后面添加L或l,建议使用L。
3.单精度浮点数用F或f标记,建议使用F
4.浮点类型的顶层存储结构与整数类型不同,float的取值范围不long的取值范围大
b.字符型(char)占2个字节
java语言中一个char数据类型可以存储一个中文汉字,因为它占有2个字节,java语言采用的是Unicode编码
c.布尔型(boolean)占1个字节
2、引用数据类型
a.类(class)
b.接口(interface)
c.数组([])
使用变量时需要注意事项
1.作用域
变量定义在哪个大括号内,他就在这个大括号内有效,并且,在同一个大括号内不能同时定义同名的变量。
2.初始化值
没有初始化值的变量不能直接使用。
只要在使用前给值就行,不一定非要在定义的时候立即给值;
推荐在定义的时候给值。
3.在一行上建议只定义一个变量,可以定义多个,但是不建议
默认类型转换(隐式转换,从小到大转换)
1、boolean类型不能转换为其他数据类型
2、byte,short,char->int->long->float->double
3、byte,short,char相互之间不转换,他们参与运算首先转换为int类型
强制转换(从大的数据类型到小的数据类型)
格式:目标数据类型 变量 = (目标数据类型)(被转换的数据)
注意:不要随意的去使用强制转换,因为它隐含了精度损失问题。
/* byte b = 130;有没有问题?如果我想让赋值正确,可以怎么做?结果是多少呢? 练习:byte b = (byte)300; */ class DataTypeDemo7 { public static void main(String[] args) { //因为byte的范围是:-128到127。 //而130不在此范围内,所以报错。 //byte b = 130; //我们可以使用强制类型转换 byte b = (byte) 130//结果是多少呢? System.out.println(b); } } /* 分析过程: 我们要想知道结果是什么,就应该知道是如何进行计算的。 而我们又知道计算机中数据的运算都是补码进行的。 而要得到补码,首先要计算出数据的二进制。 A:获取130这个数据的二进制。 00000000 00000000 00000000 10000010 这是130的原码,也是反码,还是补码。 B:做截取操作,截成byte类型的了。 10000010 这个结果是补码。 C:已知补码求原码。 符号位 数值位 补码: 1 0000010 反码: 1 0000001 原码: 1 1111110 */
/* 看程序写结果 字符串数据和其他数据做+,结果是字符串类型。 这里的+不是加法运算,而是字符串连接符。 */ class DataTypeDemo9 { public static void main(String[] args) { System.out.println("hello"+'a'+1); //helloa1 System.out.println('a'+1+"hello"); //98hello System.out.println("5+5="+5+5); //5+5=55 System.out.println(5+5+"=5+5"); //10=5+5 } }
运算符
概述:对常量和变量进行操作的符号
分类
1、算数运算符
+ - * /(取商) %(取余) ++ --
2、赋值运算符
= += -= *= /= %=
扩展的赋值运算符隐含了一个强制类型转换
S += 1 等价于 s = (s的数据类型)(s + 1)
/* 面试题: short s=1;s = s+1; short s=1;s+=1; 上面两个代码有没有问题,如果有,那里有问题? 为什么第二个没有问题呢? 扩展的赋值运算符其实隐含了一个强制类型转换 s += 1; 不是等价于 s = s + 1; 而是等价于 s = (s的数据类型)(s + 1); */ class OperatorTest { public static void main(String[] args) { //short s = 1; //s = s + 1; //System.out.println(s); short s = 1; s += 1; //好像是 s = s + 1; System.out.println(s); } }
3、比较运算符
== != < > >= <= instanceof(检查是否是类的对象)
4、逻辑运算符
&(与) |(或) ^(异或) !(非) && ||
^:相同为false不同为true
&&和&的区别
&&:只要遇到一个false就不会再执行后面的表达式
| 和 ||的区别
||: 只要遇到一个true就不会再执行后面的表达式
开发中常用的逻辑运算符:&& || !
class DataType{ public static void main(String[] args){ int a = 3; int b = 4; boolean c = ++a == 3 & ++b == 5; System.out.println("a:"+a); //4 System.out.println("b:"+b); //5 System.out.println("c:"+c);//false int a2 = 3; int b2 = 4; boolean c2 = ++a2 == 3 && ++b2 == 5; System.out.println("a2:"+a2); //4 System.out.println("b2:"+b2); //4 System.out.println("c2:"+c2);//false int a3 = 3; int b3 = 4; boolean c3 = ++a3 == 4 | ++b3 == 5; System.out.println("a3:"+a3); //4 System.out.println("b3:"+b3); //5 System.out.println("c3:"+c3);//false int a4 = 3; int b4 = 4; boolean c4 = ++a4 == 4 || ++b4 == 5; System.out.println("a4:"+a4); //4 System.out.println("b4:"+b4); //4 System.out.println("c4:"+c4);//false } }
5、位运算符(了解)
要做位运算,首先要把数据转换为二进制并且是补码
<<:左移,左边最高位丢弃,右边补齐0
>>:右移,最高位是0,左边补齐0;最高位是1,左边补齐1
>>>:无符号右移,无论最高位是0还是1,左边补齐0
&:与运算,有0则0
|:或运算,有1则1
^:异或运算,相同则0,不同则1
特点:一个数据对另外一个数据位异或两次,该数本身不变
~:反码,0变1,1变0
/* 位运算符: &,|,^,~ <<,>>,>>> 注意: 要做位运算,首先要把数据转换为二进制。 */ class OperatorDemo { public static void main(String[] args) { //&,|,^,~ int a = 3; int b = 4; System.out.println(3 & 4); System.out.println(3 | 4); System.out.println(3 ^ 4); System.out.println(~3); } } /* 分析:因为是位运算,所以我们必须先把数据换算成二进制。 3的二进制:11 00000000 00000000 00000000 00000011 4的二进制:100 00000000 00000000 00000000 00000100 &位与运算:有0则0。 00000000 00000000 00000000 00000011 &00000000 00000000 00000000 00000100 ----------------------------------- 00000000 00000000 00000000 00000000 结果是:0 |位或运算:有1则1。 00000000 00000000 00000000 00000011 |00000000 00000000 00000000 00000100 ----------------------------------- 00000000 00000000 00000000 00000111 结果是:7 ^位异或运算:相同则0,不同则1。 00000000 00000000 00000000 00000011 &00000000 00000000 00000000 00000100 ----------------------------------- 00000000 00000000 00000000 00000111 结果是:7 ~按位取反运算符:0变1,1变0 00000000 00000000 00000000 00000011 ~11111111 11111111 11111111 11111100 (补码) 补码:11111111 11111111 11111111 11111100 反码:11111111 11111111 11111111 11111011 原码:10000000 00000000 00000000 00000100 结果是:-4 */
/* <<:左移 左边最高位丢弃,右边补齐0 >>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1 >>>:无符号右移 无论最高位是0还是1,左边补齐0 面试题: 请用最有效率的方式写出计算2乘以8的结果? 2 * 8 2 << 3 */ class OperatorDemo3 { public static void main(String[] args) { //<< 把<<左边的数据乘以2的移动次幂 System.out.println(3 << 2); //3*2^2 = 3*4 = 12; //>> 把>>左边的数据除以2的移动次幂 System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6 System.out.println(24 >>> 2); System.out.println(-24 >> 2); System.out.println(-24 >>> 2); } } /* 计算出3的二进制:11 00000000 00000000 00000000 00000011 (00)000000 00000000 00000000 0000001100 >>的移动: 计算出24的二进制:11000 原码:10000000 00000000 00000000 00011000 反码:11111111 11111111 11111111 11100111 补码:11111111 11111111 11111111 11101000 11111111 11111111 11111111 11101000 1111111111 11111111 11111111 111010(00) 补码 补码:1111111111 11111111 11111111 111010 反码:1111111111 11111111 11111111 111001 原码:1000000000 00000000 00000000 000110 结果:-6 >>>的移动: 计算出24的二进制:11000 原码:10000000 00000000 00000000 00011000 反码:11111111 11111111 11111111 11100111 补码:11111111 11111111 11111111 11101000 11111111 11111111 11111111 11101000 0011111111 11111111 11111111 111010(00) 结果: */
/* 面试题: 请自己实现两个整数变量的交换 注意:以后讲课的过程中,我没有明确指定数据的类型,默认int类型。 */ class OperatorTest { public static void main(String[] args) { int a = 10; int b = 20; System.out.println("a:"+a+",b:"+b); //方式1:使用第三方变量(开发中用的) /* int c = a; a = b; b = c; System.out.println("a:"+a+",b:"+b); System.out.println("------------"); */ //方式2:用位异或实现(面试用) //左边:a,b,a //右边:a ^ b /* a = a ^ b; b = a ^ b; //a ^ b ^ b = a a = a ^ b; //a ^ b ^ a = b System.out.println("a:"+a+",b:"+b); */ //方式3:用变量相加的做法 /* a = a + b; //a=30 b = a - b; //b=10 a = a - b; //a=20 System.out.println("a:"+a+",b:"+b); */ //方式4:一句话搞定 b = (a+b) - (a=b); //b=30-20=10,a=20 System.out.println("a:"+a+",b:"+b); } }
6、三目运算符
格式:
(关系表达式)?表达式1:表达式2;
如果条件为true,运算的结果是表达式1;
如果条件为false,运算的结果是表达式2;
/* 练习: 获取两个整数中的最大值 获取三个整数中的最大值 比较两个整数是否相同 */ class OperatorTest { public static void main(String[] args) { //获取两个整数中的最大值 int x = 100; int y = 200; int max = (x > y? x: y); System.out.println("max:"+max); System.out.println("--------"); //获取三个整数中的最大值 int a = 10; int b = 30; int c = 20; //分两步: //A:先比较a,b的最大值 //B:拿a,b的最大值在和c进行比较 int temp = ((a > b)? a: b); //System.out.println(temp); int max1 = (temp > c? temp: c); System.out.println("max1:"+max1); //一步搞定 //int max2 = (a > b)?((a > c)? a: c):((b > c)? b: c); //这种做法不推荐。 //int max2 = a > b?a > c? a: c:b > c? b: c; //System.out.println("max2:"+max2); System.out.println("--------"); //比较两个整数是否相同 int m = 100; int n = 200; //boolean flag = (m == n)? true: false; boolean flag = (m == n); System.out.println(flag); } }
键盘录入数据
1、导包:import java.util.Scanner;
2、创建对象:Scanner sc = new Scanner(System.in);
3、接收数据:int x = sc.nextInt();
/* 键盘录入两个数据,并对这两个数据求和,输出其结果 */ import java.util.Scanner; class ScannerTest{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int a = sc.nextInt(); int b = sc.nextInt(); System.out.println("a+b="+(a+b)); } }
流程控制语句
1、顺序结构
是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
总的来说:写在前面的先执行,写在后面的后执行
2、选择结构
也被称为分支结构
有特定的语法规则,代码要对具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码
java语言提供了两种不同的选择结构语句
if语句
if(关系表达式1){
语句体1;
}else if(关系表达式2){
语句体2;
}
...
else{
语句体3;
}
/* 三种if语句分别适合做什么事情呢? 格式1:适合做单个判断if 格式2:适合做两个判断if... else 格式3:适合做多个判断if ... else if ... else 需求: 键盘录入x的值,计算出y的并输出。 x>=3 y = 2x + 1; -1<=x<3 y = 2x; x<=-1 y = 2x – 1; 分析: A:由于数据要键盘录入,所以必须使用Scanner。 B:由于是三种判断,所以我们选择if语句格式3。 */ import java.util.Scanner; class IfTest2 { public static void main(String[] args) { //创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入x的值:"); int x = sc.nextInt(); //定义一个y int y; //用if语句格式3进行判断 if(x >= 3) { y = 2*x + 1; }else if(x>=-1 && x<3) { y = 2*x; }else { y = 2*x - 1; } System.out.println("y:"+y); } }
if语句与三目运算的区别:三元运算符实现的,都可以采用if语句实现。反之不成立。
/* 由于if...else语句也完成了三元运算符可以完成的效果。 所以,我们就认为他们可以完成一样的操作。 但是,他们就一点区别没有吗?肯定不是。 区别: 三元运算符实现的,都可以采用if语句实现。反之不成立。 什么时候if语句实现不能用三元改进呢? 当if语句控制的操作是一个输出语句的时候就不能。 为什么呢?因为三元运算符是一个运算符,运算符操作完毕就应该有一个结果,而不是一个输出。 */ class IfDemo4 { public static void main(String[] args) { //获取两个数据的最大值 int a = 10; int b = 20; //用if语句实现 int max1; if(a > b) { max1 = a; }else { max1 = b; } System.out.println("max1:"+max1); //用三元改进 int max2 = (a > b)? a: b; System.out.println("max2:"+max2); System.out.println("----------"); //判断一个数据是奇数还是偶数,并输出是奇数还是偶数 int x = 100; if(x%2 == 0) { System.out.println("100是一个偶数"); }else { System.out.println("100是一个奇数"); } //用三元改进 //这种改进是错误的。 //String s = (x%2 == 0)?System.out.println("100是一个偶数");:System.out.println("100是一个奇数");; } }
使用if语句的注意事项
/* if语句的注意事项: A:比较表达式无论简单还是复杂,结果必须是boolean类型 B:if语句控制的语句体如果是一条语句,大括号可以省略; 如果是多条语句,就不能省略。建议永远不要省略。 C:一般来说:有左大括号就没有分号,有分号就没有左大括号 */ class IfDemo2 { public static void main(String[] args) { int x = 10; if(x == 10) { System.out.println("x等于10"); } if((x > 5) || (x == 10)) { System.out.println("x大于或者等于10"); } System.out.println("-------------------"); int a = 100; /* if(a == 100) { System.out.println("a的值是100"); } */ if(a != 100) { System.out.println("a的值是100"); System.out.println("over"); } System.out.println("-------------------"); int b = 100; if(b != 100); //这里其实是有语句体的,只不过是空语句体。 //代码块 { System.out.println("b的值是100"); System.out.println("over"); } } }
switch语句
switch(表达式){
case 值1:
语句体1;
break;
...
default:
语句体n+1;
break;
}
说明:
表达式的取值范围:byte,short,int,char;JDK5之后支持枚举,JDK7之后支持字符串
case后面只能是常量,不能是变量,多个case后面的值不能相同
3、循环结构
循环语句的组成
1、初始化语句
一条或多条语句,这些语句完成一些初始化操作
2、判断条件语句
这是一个boolean表达式,这个表达式能决定是否执行循环体
3、循环体语句
这个部分是循环体语句,也就是要多次做的事情
4、控制条件语句
这个部分在一次循环体结束后,下次循环判断条件执行前执行,通过用于控制循环条件中的变量,使得循环在合适的时候结束
for循环,while循环,do...while循环的区别
do...while循环至少执行一次循环体
for,while循环必须先判断条件是否成立,然后决定是否执行循环体语句
在使用时,优先考虑for,其次考虑while,最后考虑do...while
控制跳转语句
break:中断
使用场景:
1、在选择结构switch语句中
2、在循环语句中
注意:离开上面的两个场景,无意义(报错信息:在switch或loop外部中断)
作用:
1、跳出单层循环
2、跳出多层循环
带标签的跳出
格式:标签名:循环语句
标签名要符合Java的命名规则
continue:继续
使用场景:
在循环语句中
离开使用场景的存在是没有意义的
作用:退出本次循环,继续下次循环,也可以贷标签使用
class ScannerTest{ public static void main(String[] args){ //定义标签wc表示外层循环 wc:for(int x=0;x<4;x++){ //定义标签nc表示内层循环 nc:for(int y=0;y<6;y++){ if(y==2){ //break wc;//** continue wc; // ******** } System.out.print("*"); } System.out.println(); } } }
return:返回,作为一个函数的返回
方法和数组
方法就是完成特定功能的代码块
在很多语言中都有函数的定义,函数在java中被称为方法
格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...){
函数体;
return 返回值;
}
详细解释:
修饰符:目前就用 public static ,后面再详细的讲解其他的修饰符
返回值类型:就是功能结果的数据类型
方法名:符合命名规则即可,方便我们的调用
参数:
实际参数:就是实际参与运算的
形式参数:就是方法定义上的,用于接收实际参数的
参数类型:就是参数的数据类型
函数体:就是完成功能的代码
return:用于结束方法
返回值:就是功能的结果,由return带给调用者。
方法的调用:
带返回值的方法的调用
1、单独调用:方法名(实参1,实参2...);
2、输出调用:System.out.println(方法名(实参1,实参2...));
3、赋值调用:数据类型 变量名 = 方法名(实参1,实参2...);
无返回值(void)的方法的调用
只能单独调用
说明:方法与方法是平级关系,不能嵌套定义
方法的重载:在一个类中,方法名相同,参数的个数或参数类型不同,与返回值无关
package com.xdl; /* * 方法的重载(Overload),多个方法的名称一样,但是参数列表不一样。 * 好处:主要记住方法的名称,就可以实现类似的功能。 * 方法重载与下列因素相关: * 1、参数个数不同 * 2、参数类型不同 * 3、参数的多类型顺序不同 * 方法重载与下列因素无关: * 1、与参数的名称无关 * 2、与方法的返回值类型无关 * */ public class MethodOverload { public static void main(String[] args) { System.out.println(sum(1, 2)); System.out.println(sum(1, 2, 3)); System.out.println(sum(1.0, 1)); System.out.println(sum(1, 1.0)); } public static int sum(int a, int b) { int res = a + b; return res; } public static int sum(int a, int b, int c) { int res = a + b + c; return res; } public static int sum(double a, int b) { System.out.println("double sum"); return (int) (a + b); } public static int sum(int a, double b) { System.out.println("double2 sum"); return (int) (a + b); } }
java中参数传递问题
基本数据类型:形式参数的改变对实际参数没有影响,基本数据类型赋值将实际值赋给变量
引用数据类型:形式参数的改变直接影响实际参数,引用数据类型赋值是将实际值的地址赋给变量
数组的概念:
数组是存储同一种数据类型多个元素的集合,也可以看成是一个容器
数组既可以存储基本数据类型,也可以存储引用数据类型
数组的定义格式:
格式1:数据类型[] 数组名;(推荐使用)
格式2:数据类型 数组名[];
数据的遍历方式:for(数据类型 变量名 :数组名){...}
class ScannerTest{ public static void main(String[] args){ int[] arr = new int[3]; System.out.println(arr);//[I@15db9742 地址值 for(int x : arr){ System.out.println(x); //0 } } }
数组初始化概念:
就是为数组中的数组元素分配内存空间,并为每个数组元素赋值
数组的初始化方式:
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
数据类型[] 数组名 = new 数据类型[数组长度]
例如:int[] arr = new int[3];
new关键字为数组分配内存空间
静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。(常用)
数据类型[] 数组名 = new 数据类型[]{元素值1,元素值2,...};
简化格式:
数据类型[] 数组名 = {元素值1,元素值2,...};
注意:不要同时动态和静态进行,int[] arr = new int[3]{1,2,3};是错误的
数组的长度:数组名.length
数组的常见操作
1、遍历数组
class ScannerTest{ public static void main(String[] args){ int[] arr = {2,3,4,5,6,7,8,9}; printArray(arr); } public static void printArray(int[] arr){ System.out.print("["); for(int i = 0; i<arr.length; i++){ if(i == arr.length - 1){ System.out.print(arr[i]+"]"); }else{ System.out.print(arr[i]+","); } } } }
2、求数组的最值
class ScannerTest{ public static void main(String[] args){ int[] arr = {2,3,4,5,6,7,8,9}; int max = getMax(arr); int min = getMin(arr); System.out.println("MAX:"+max); System.out.println("MIN:"+min); } public static int getMax(int[] arr){ int max = arr[0]; for(int i = 1; i<arr.length; i++){ if(arr[i] > max){ max = arr[i]; } } return max; } public static int getMin(int[] arr){ int min = arr[0]; for(int i = 1; i<arr.length; i++){ if(arr[i] < min){ min = arr[i]; } } return min; } }
3、逆序
class ScannerTest{ public static void main(String[] args){ int[] arr = {2,3,4,5,6,7,8,9}; System.out.println("逆序前:"); printArray(arr); System.out.println("逆序后:"); reverse(arr); printArray(arr); } public static void reverse(int[] arr){ for(int begin=0,end=arr.length-1; begin < end; begin++, end--){ int temp = arr[begin]; arr[begin] = arr[end]; arr[end] = temp; } } public static void printArray(int[] arr){ System.out.print("["); for(int i = 0; i<arr.length; i++){ if(i == arr.length - 1){ System.out.print(arr[i]+"]"); }else{ System.out.print(arr[i]+","); } } } }
4、查表
import java.util.Scanner; class ArrayTest4 { public static void main(String[] args) { //定义一个字符串数组 String[] strArray = {"星期一","星期二","星期三","星期四","星期五","星期六","星期日"}; //创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入一个数据(0-6):"); int index = sc.nextInt(); System.out.println("你要查找的日期是:"+strArray[index]); } }
5、基本查找
/* 需求:数组元素查找(查找指定元素第一次在数组中出现的索引) 分析: A:定义一个数组,并静态初始化。 B:写一个功能实现 遍历数组,依次获取数组中的每一个元素,和已知的数据进行比较 如果相等,就返回当前的索引值。 */ class ArrayTest5 { public static void main(String[] args) { //定义一个数组,并静态初始化 int[] arr = {200,250,38,888,444}; //需求:我要查找250在这个数组中第一次出现的索引 int index = getIndex(arr,250); System.out.println("250在数组中第一次出现的索引是:"+index); int index2 = getIndex2(arr,250); System.out.println("250在数组中第一次出现的索引是:"+index2); int index3 = getIndex2(arr,2500); System.out.println("2500在数组中第一次出现的索引是:"+index3); } /* 需求:查找指定数据在数组中第一次出现的索引 两个明确: 返回值类型:int 参数列表:int[] arr,int value */ public static int getIndex(int[] arr,int value) { //遍历数组,依次获取数组中的每一个元素,和已知的数据进行比较 for(int x=0; x<arr.length; x++) { if(arr[x] == value) { //如果相等,就返回当前的索引值。 return x; } } //目前的代码有一个小问题 //就是假如我要查找的数据在数组中不存在,那就找不到,找不到,你就对应的返回吗? //所以报错。 //只要是判断,就可能是false,所以大家要细心。 //如果找不到数据,我们一般返回一个负数即可,而且是返回-1 return -1; } public static int getIndex2(int[] arr,int value) { //定义一个索引 int index = -1; //有就修改索引值 for(int x=0; x<arr.length; x++) { if(arr[x] == value) { index = x; break; } } //返回index return index; } }
6、删除数组中的0元素
class ScannerTest{ public static void main(String[] args){ int[] arr = {2,3,0,4,5,0,0,6,7,8,9}; int size = delete0(arr); int[] newArr = new int[size]; for(int i =0; i<size;i++){ newArr[i] = arr[i]; } printArray(newArr); } public static int delete0(int[] arr){ int size = arr.length; for(int i = 0; i<arr.length; i++){ if(arr[i] == 0 && i != arr.length-1){ //首先把所有的零元素放到数组的末尾 for(int j = i; j<arr.length -1; j++){ arr[j] = arr[j+1]; } i--; size--; } } return size; } public static void printArray(int[] arr){ System.out.print("["); for(int i = 0; i<arr.length; i++){ if(i == arr.length - 1){ System.out.print(arr[i]+"]"); }else{ System.out.print(arr[i]+","); } } } }
二维数组:其实就是一个元素为以为数组的数组
格式1:
数据类型[][] 数组名 = new 数据类型[m][n];
数据类型 数组名 [][] = new 数据类型[m][n];
数据类型[] 数组名[] = new 数据类型[m][n];
格式2:
数据类型[][] 数组名 = new 数据类型[m][];
格式3
数据类型[][] 数组名 = new 数据类型[][]{{元素,...}{元素...}}
数据类型[][] 数组名 = {{元素,...}{元素...}}
说明:m表示二维数组有多少个一位数组(必须的),n表示每一个一位数组的元素个数(不是必须的)
int x, y;
int[] x,y[];表示定义一个一位数组x,一个二维数组y
Java中的内存分配
Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
1、栈:存储局部变量
特点:栈内存的数据用完就释放掉(效率高)
2、堆:存储new出来的东西
特点:
1、每一个new出来的东西都有地址值
2、每个变量都有默认值
byte,short,int,long的默认值是0
float,double的默认值是0.0
char的默认值是'\u0000'
boolean的默认值是flase
引用类型(类,接口,数组)的默认值是null
3、使用完毕就变成垃圾,但是并没有立即回收,会在垃圾回收器空闲的时候回收
3、方法区(在面向对象部分讲解)
4、本地方法区(和系统相关)(了解)
5、寄存器(给CPU使用)(了解)
局部变量:在方法定义中或方法声明上的变量都称为局部变量
结合以上的知识点,做一道加密编程题,题目如下:
/* 某个公司采用公用电话传递数据信息,数据是小于8位的整数,为了确保安全, 在传递过程中需要加密,加密规则如下: 首先将数据倒序,然后将每位数字都加上5,再用和除以10的余数代替该数字, 最后将第一位和最后一位数字交换。 请任意给定一个小于8位的整数, 然后,把加密后的结果在控制台打印出来。 */ import java.util.Scanner; class Encryption{ public static void main(String[] args){ //创建键盘输入对象 Scanner sc = new Scanner(System.in); int number = sc.nextInt(); String stringNumber = encryption(number); System.out.println(stringNumber); } //实现一个加密函数 public static String encryption(int number){ int [] arr = new int[8]; int index = 0; //把数字倒序的放入数组中 while(number > 0 ){ arr[index++] = number % 10; number /= 10; } //把数组中的元素加五再除以十 for(int i = 0; i < index; i++){ arr[i] += 5; arr[i] %= 10; } //把数组中第一个元素与最后一个元素对换位置 int temp = arr[0]; arr[0] = arr[index-1]; arr[index-1] = temp; String stringNumber = ""; //把数组中的元素拼接起来 for(int i = 0; i<index; i++){ stringNumber += arr[i]; } return stringNumber; } }