异常类型:
InputMisMatch Exception----输入类型不匹配
Array Index OutOf Bounds Exception----数组索引越界
NegativeArraySizeException----运行时的异常,创建数组的时候长度给了负数,数组的长度不合法
基本概念
JVM:
JVM Java Virtual Machine虚拟机
JVM会在内存中开辟一块空间,从而将源文件编译成字节码文件
##计算机硬件组成:
内存(条形的芯片 临时执行使用的)、硬盘(矩形的 有机械硬盘和固态硬盘 永久性保存的)
应用在系统之上的软件=应用软件
硬盘上的文件有不同的格式,所以有不同的后缀名(.txt .doc .ppt .xls等),需要不同的运行环境的支持
源文件.java 字节码文件.class
JRE:
Java Runtime Environment 运行环境
可以运行别人写好的程序
##JDK:
- Java Development Kit 开发工具包,这些开发工具包全部存储于bin目录,有两个很重要的工具:javac.exe(编译工具,编译形成字节码文件)和java.exe(执行工具,形成字节码文件后用这个工具执行),这些工具只能在底层的doc窗口才能看到效果
- 开发时需要用到的工具,为了开发后能够运行,所以:JDK包含JRE,JRE包含JVM
- include文件夹包含了其他语言写的程序
- jre文件夹包含运行环境
- lib文件夹包含人家写好的所有的java类,以.jar形式存在
- release包含配置文件
- src.zip压缩文件存储源代码
搭建环境(安装JDK)
在官方网站下载JDK安装程序,这是Oracle公司的产品,所以去www.oracle.com下载
卸载的话去控制面板卸载
===============================
写一个基本的java源代码:
1.首先新建一个记事本,将后缀改为.java,然后以记事本形式打开该源文件
2.先写一个关键字class---->表示类的意思
3.类后面起一个名字---->理论上可以随便写,但是有规则和规约
命名规则和规约:
规则 名字中可以含有如下信息:
字母(区分大小写,52个英文字母可以用)
数字(0-9可以用,但不可以用做开头)
符号(英文符号 仅两个: _ $)
中文(强烈不推荐---->当做不行)
规约:
类的名字 需要首字母大写,例如TestOne,如果两个以上的单词,则每个单词的首字母都要大写
变量的名字 需要首字母小写,例如testOne,如果两个以上的单词,则除了第一个单词之后的每个单词的首字母都要大写,遵循驼峰式命名规约
起名字的时候要见名知义,尽量使用英文单词,增强程序可读性
4.类名后边组大括号,表示当前类的内容
利用JDK包提供的工具,进行代码的编译及执行:
- 由于源代码.java的所在路径和编译工具javacexe并不在一起,而且编译工具直接双击的话是一个黑色对话框一闪而过,编译工具在doc命令窗口才可以使用---->window键+R打开运行窗口,输入cmd指令打开doc命令行窗口
- 刚打开doc窗口,默认在C盘,切换到盛放编译工具的盘,我放在了D盘/java/jdk/bin/下:
1、d:(cd..是退出一层文件夹)
2、cd java
3、cd jdk*(表示切换到所有jdk开头的文件夹,此时打开的是jdks文件夹)
4、cd jdk*(这时打开的是jdk1.8.0_281文件夹)
5、cd bin
6、javac(表示直接运行这个工具),可以看到好多信息
配置环境变量:
- 我的电脑(右击)—属性—高级系统设置—环境变量—用户变量(上半部分)—变量名Path—双击或者编辑—将安装工具的目录放到里边去(D:\Java\jdks\jdk1.8.0_281\bin),点击新建,复制进去—如果要将这个放到第一个,选中点击上移即可—确定—确定—确定
配置path是为了让工具在任何位置都可以用
classPath 作用是不管源文件在哪,生成的class文件都统一存储在配置的目录下(就是生成的字节码文件的存储位置)
JAVA_HOME 目的是为了让路径的写法变得简单(相对路径的写法)
例如:JAVA_HOME C://program files/java/jdk
path %JAVA_HOME%/bin
利用javac工具编译:
doc窗口:
e:(切换到e盘,因为我把test测试代码放到了e:\javatest)
cd e:
cd test
javac Test.java(javac编译Test.java文件)
- 若我的Test1.java里的代码编写正确的话,javac编译了Test1.java文件后,文件夹就会多一个类名.class文件,此时我命名的类名为Demo
- 编译完成后,使用java.exe工具来运行:
java Demo(注意:运行的时候不需要写后缀.class)
结果提示运行错误:
错误: 在类 Demo 中找不到 main 方法, 请将 main 方法定义为:
public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application
这是因为我编写的Test1.java文件里没有主方法,主方法是程序入口
class Demo{
public static void main(String[] args){
}
}
public:叫做访问权限修饰符,表示共有的
static:特征修饰符,有且只有一份
void:表示当前程序访问完没有返回结果
main:必须叫main,方法名
String[] args:参数列表
String:字符串
[]:数组
args:变量名(arguments)
这个主方法里{}写的是主方法的执行过程,这一堆除了args这个变量名可以改都是固定的
- 由于修改了Test1.java,所以重新编译,再执行:
C:\test>javac Test1.java
C:\test>java Demo
什么效果也没有,是因为他执行了一个方法,但是方法里什么都没有做,所以再编写方法:
class Demo{
public static void main(String[] args){
System.out.println("fgsdas");
}
}
方法里写的表示输出fgsdas,print后加ln是换行的意思:
C:\test>javac Test1.java
C:\test>java Demo
fgsdas
C:\test>
这个FGSDAS后的空行就是ln发挥的作用
这就是基本的java代码的编写了
但是这样的话,会有一个问题,就是生成文件和字节码文件的名字不一致,如果文件数目多的话会记不住,所以这样改进:
在class前边加一个public,但是加了public之后运行会出错误,这是因为加了public后,要求当前类的名字要与字节码文件的名字一致:
public class Test{
public static void main(String[] args){
System.out.println("fgsdas");
}
}
以上是一个标准类的写法!!
===============================
标题数据类型
- 基本数据类型有8个:
4个整型:
按照存储的单位大小由小到大:
byte(字节型)、short(短整型)、int(整型)、long(长整型64位)
2个浮点型:
从精确长度由小到大:
float(单精度32)、double(双精度64)
1个字符型:
char
1个布尔型:
boolean
- 引用数据类型:
数组[]
类class(抽象类abstract class)
接口interface
枚举enum
注解@interface
基本数据类型;
整型:
byte 字节型 1字节
1byte== 8bit(敏感单元位) 0 0000000 256种组合
第一个bit位置记录符号:0表正数、1表负数
所以数值的范围是 -2的7次方 ~ 2的7次方-1(因为0放到了正的那边)即-128~127
short 2字节 == 16bit 65526种组合
所以数值的范围是 -2的15次方 ~ 2的15次方-1(因为0放到了正的那边)即-32768~32767
int 4字节 == 32bit
所以数值的范围是 -2的31次方 ~ 2的31次方-1(因为0放到了正的那边)即-2147483648~2147483647
long 8字节==64bit
所以数值的范围是 -2的63次方 ~ 2的63次方-1(因为0放到了正的那边)
浮点型:
float 32bit 4字节
0 000000000 00000000000000000000
第一位表示符号,然后九位表示整数部分,剩下的表示小数部分
double 64bit 8字节
第一位表示符号,然后十九位表示整数部分,剩下的表示小数部分
字符型:
char 16bit 2字节 中文是Unicode编码 范围是0-65535
中文两个字节,英文、符号、数字一个字节
键盘能输出来的都算字符型,但是字符中数字和整数的数字冲突,为了区分,所以每个字符的前后各加单引号
布尔型:
boolean 1bit 1/8字节
true、false
===============================================
java常量与变量
常量
代表程序在运行过程中不能再次改变的值
常量作用:
- 固定的值 计算过程中经常用到的值,便于程序计算,比如圆周率pi
- 代表一个含义
这样的值可以算作常量:- 固定不变的值,比如:1 3.14 ‘a’ true
可以认为所有基本类型的值固定不变- 特殊的常量
例如:“abc”—>String类型,这是一个引用数据类型,值很特殊,可以简单的视为常量- 自己创建的空间,存储一个值,让它固定起来,比如:
final int up = 1;用final修饰的这个空间的值是不能改变的
常量的存储形式是以二进制形式存储的:
- 如果是整数,比如1---->以32位bit位形式存储(相当于int型)
- 如果是小数,比如3.4---->以64位bit位形式存储(相当于double型)
##变量
指程序执行过程中可以改变的
变量是一个内存空间(小容器),变量空间在创建(声明)的时候必须要指定数据类型和变量空间的名字,且变量空间只能存储一个内容(值、引用),变量空间的内容可以改变
创建变量时需要注意命名问题,上边有记录命名的规则和规约
变量这样创建/声明:
数据类型 变量名字; 比如: int a;或者String b;
注意:变量是一个空间,可以只创建空间不存放内容,变量空间创建后没有默认的内容,是空的,空的变量空间不能拿来使用,会出现编译错误
byte x;//声明一个变量空间,空间名叫x,空间内要求存储的数据类型是byte整数
x=1;//讲一个1赋值到x空间内进行存储
也可以写成一句:
byte x = 1;
- 变量空间x存储在栈内存里
- 常量1存储在常量池(即常量缓冲区)里
计算机底层做了这些:
1.在硬盘先创建一个文件Test.java
2.文件上的内容是我们编写的源代码:(向计算机发出指令)
public class Test{
public static void main(String[] args){
byte x;
x=1;
}
}
3.将Test.java源文件—>编译—>成为Test.class文件,这个文件里的内容我们看不懂,留给计算机识别
4.在内存中执行:将硬盘上的Test.class内容加载到内存里
5.我们写好的指令会执行内存的空间,赋值、变化。。。
需要注意:float x = 3.4F;
long y = 2147489999L;//如果超过int的取值范围2147483647就在后边加一个L
================================================
类型转化
类型之间的转换问题:
- 同种数据类型之间是可以直接进行赋值操作的:
int a = 1;
int b = a;
float x = 3.4;
float y = x;
- 数据类型不同的空间之间的赋值—>转换问题
同种大数据类型之间才能发生转换
基本类型----基本类型之间 可以直接转换(自动或强制)
引用类型----引用类型之间 可以直接转换(自动或强制)–上转型 下转型
基本类型----引用类型之间 不可以直接转换(间接转换–包装类/封装类) - 保证大数据类型一致的前提下:
1、基本类型----基本类型
保证大数据类型相同的前提下---->小数据类型相同的情况下:(比如都是整型或都是浮点型,比较的是内存空间的大小)
byte a= 1;
int b = a;//将一个小空间的值存到大空间里,自动直接转化
int a = 1;
byte b = (byte)a;//将一个大空间的值存到小空间里,强制类型转换
float x = 3.4F;
double y = x;//自动直接转化
double x = 3.4;
float y = (float)x;//强制类型转换
大空间变量可以直接存储小空间的数据
小空间变量不可以直接存储大空间的数据(需要强制类型转换)
转换过程写法都好用,如果转换过程中数值范围超过边界,数值可能会有损失:
int a = 1000;
byte b = (byte)a;//编译好用,执行后b存放的值一定发生变化
00000000 00000000 00000011 11101000---->只保留最后的8bit位
小数据类型不同的情况下:
(比如整型----浮点型):
两个比较精确程度,浮点型的精确程度更高,可以直接存放整数,反之需要强制类型转换(强行将小数点之后的部分去掉,只保留整数):
float a = 1.0F;
int b = (int)a;//强制转化,出来b为1
float a = 1.9F;
int b = (int)a;//强制转化,出来b为1
任何一个浮点型都可以直接存放一个整数:
int a = 1;
float b = a;//自动转换
(比如字符型----整型):
每一个字符都对应一个Unicode码
char x = 'a';
int y = x;//可以转化,出来y为97
int x = 97;
char y = (char)x;//强制转化,出来y为a
byte x = 97;
char y = (char)x;//强制转化,出来y为a
布尔类型很特殊,不能与其他基本类型之间发生转化
2、引用类型----引用类型
可以直接转化(自动 强制)
3、基本类型----引用类型
不可以直接转化(间接-桥梁-包装类)
=========================================
运算符号
Java运算符:
运算符是用来指明操作数的运算方式,有两种分类:
按照操作数的数目来进行分类:
- 单目 a++
- 双目 a+b
- 三目 (a>b)?x:y;
按照运算符的功能进行分类:
算术运算
例如 + - * / %(取余、取模)
++(自增) --(自减)
x++;//x=x+1;//x空间的值自增一个,即:将x变量空间的内容先取出,常量区取出1,进行计算,再次存回x空间(x在想要做交换的时候会产生一个临时的副本空间(备份))
++x;// 对于x空间内的值来讲都是一致的,最终的结果都自增了一个int x = 1; int y = x++;//++在后,先赋值(计算)后自增-->结果x=2,y=1(++在变量的后面,先备份后自增,将副本空间内的值赋给别人,也就是y)
int x = 1; int y = ++x;//结果x=2,y=2(++在变量的前面,先自增后备份)
int a = 1; a=a++;//a==?结果a=1
int a = 1; for(int i=1;1<=100;i++){ a = a++; }//a==?最终结果a=1
int m = 1; int n = 2; int sum = m++ + ++n - n-- - --m + n-- - --m//m==?0 n==?1 sum==?2
赋值运算
= 是赋值符号,将等号右边的内容(值 引用)存入左边的变量空间内
+= -= *= /= %= 符合运算符
int x = 1;
x+=2;//结果x=3
int x = 1;
x=x+2;//结果x=3
byte x = 1;//常量1是32bit位的,但是=做了自动转化
x+=2;//结果x=3
//+进行自动类型提升,然后加上2后为3,=再进行自动转化
byte x = 1;//常量1是32bit位的,但是=做了自动转化
x=x+2;//编译出错,类型从int转化成byte可能有损失
x空间的值取出来,从常量区取过来2,进行加法运算,结果重新存回到x变量空间内
x空间–>1 8bit 00000001
常量区–>2 32bit
00000000 00000000 00000000 00000010
+的作用是进行自动类型提升,即由8bit–>32bit
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010
相加:00000000 00000000 00000000 00000011==3
所以将3重新存回到x变量空间,但是x是8bit位的,存不下,所以需要强制类型转化:
byte x = 1;//常量1是32bit位的,但是=做了自动转化
x = (byte)(x+2);
因为=后边是个表达式,所以需要强制转化,若果是个常量,就会自动转化
关系运算(也叫比较运算)
有 > >= < <= != ==(对象instanceof类)
- 区分 = 和 ==
= 赋值符号 将=后面的内容(结果或值)存入左边的变量空间内
== 比较符号 比较==前边和后边的元素(值/引用)是否一致
- 比较运算符的最终结果是啥:
boolean布尔类型 true false
逻辑运算
&逻辑与(两个条件都true,最终就true) |逻辑或(两个条件有一个true,最终就true) ^逻辑异或(两个条件不一样最终就true) !逻辑非(将原来的条件的结果取反) &&短路与(当前面的条件的值的结果为false的时候会发生短路,最终结果是false;如果第一个条件的结果是true,那就跟&逻辑与一样计算。短路的是&&之后所有的计算过程,如果发生了短路,性能比&稍微好一点,&逻辑与和&&短路与从执行的结果来看没有任何区别,&&短路与不一定提高性能,只有当前面的条件为false的时候才会提高性能) ||短路或(当前面的条件的值的结果为true的时候会发生短路,最终结果是true;如果第一个条件的结果是false,那就跟&逻辑与一样计算。)
1、逻辑运算符前后连接的应该是两个boolean的值,最后的结果还是布尔类型的值
位(bit)运算
&按位与 、 |按位或 、 ^按位异或 、 ~按位取反 、 <<按位左位移 、 >>按位右位移 、 >>>按位右位移(无符号)
&按位与(比如3 & 5 = ?):
1、将3和5转化成二进制的表示形式
2、竖着按照对应的位置进行&|^计算(1当做true,0当做false)
3、将计算后的二进制结果转化为十进制
~按位取反:
- 知识补充:
正数的原码、反码、补码是一样的。比如6:
原码:00000000 00000000 00000000 00000110
反码:00000000 00000000 00000000 00000110
补码:00000000 00000000 00000000 00000110
负数的反码在原码的基础上符号位不动,其余位取反,补码在反码的基础上加1。比如-6:
原码:10000000 00000000 00000000 00000110
反码:11111111 11111111 11111111 11111001
补码:11111111 11111111 11111111 11111010
计算机中不管是正数还是负数,存储的形式都是以补码存储的。反码是一种表示形式,取反是一种计算过程
(每个位置都取反)
所以6在计算机中的表示形式是:00000000 00000000 00000000 00000110
当求~6 = ?时,取反得:11111111 11111111 11111111 11111001,转化为二进制是-7
<<按位左位移(比如6<<1 = ?、6<<2 = ?):
00000000 00000000 00000000 00000110
00000000 00000000 00000000 00001100
相当于将这个数乘以2的位移次幂
<<按位右位移:
(正数时比如6>>1 = ?、6>>2 = ?)
00000000 00000000 00000000 00000110
00000000 00000000 00000000 00000011
相当于将这个数除以2的位移次幂
(负数时比如-6>>1 = ?、-6>>2 = ?)
11111111 11111111 11111111 11111010
11111111 11111111 11111111 11111101
相当于保留符号位置,原来的符号位是1,还填1,然后再将二进制转化为二进制
>>>按位右位移(无符号)(比如-6<<<1 = ?、-6<<<2 = ?):
11111111 11111111 11111111 11111010
01111111 11111111 11111111 11111101
不保留符号位置,不管是什么都填0
======================================
Java体系
- 基础部分 JavaSE
面向对象的编程思想 ArrayBox LinkedBox
集合 String
I/O流技术 MVC 缓存 文件–数据库 事务 反射注解 IOC - Level One
数据库 本质就是文件
JDBC 本质就是I/O 手动设计一个ORM–原 理 MyBatis
WEB 本质就是Socket IO String
手动设计一个容器(服务器)
Tomcat
Servlet JSP解析—>手动设计一个WEB框架
Filter AJAX
*Level Two
框架部分
SSM: Spring SpringMVC MyBatis
SSH: Spring Struts Hibernate
Linux Maven Git SVN - 分布式 大数据
==================================
Java语法结构1
顺序结构
分支结构
单分支if
if结构:
if(值--boolean型)
{单行语句;}/{多行语句}//执行单行或多行
if else结构:
if(条件){
代码1
}else{
代码2
}
嵌套结构:
if(){
}else if(){
}else if(){
}else{
}
知识补充:Scanner类的引用:
lib文件夹会提供一个类库,有一个Scanner类,也就是开发者会给我们提供一个好的类文件Scanner.java,我们引用就行。
想要利用Scanner类需要如下三步:
1、在类上边的第一行导入包:
import java.util.Scanner;
2、需要输入之前new一个对象:
Scanner 对象名 = new Scanner(System.in);
3、通过 对象名.方法 让他来做事:
int = nextInt();//读取输入的信息,这个是读取输入的数字类型的文字
String = nextLine();//读取输入的信息,这个是读取字符串
比如:
import java.util.Scanner;//导包
Scanner input = new Scanner(System.in);//创建对象
System.out.printIn("请您输入一个数字:");
int Day = input.nextInt();//对象调用一个方法,这个方法的返回值是day
多分支switch
switch(值){//这个值可以是byte short int char类型的
case 值1:
代码1;
break;//可有可无
case 值2:
代码2;
default:
代码;
}
循环结构
有for while do…while,就是重复不停的做同样的事情,需满足三个条件:初始值、终点判定条件、变化量
for结构
for(1初始值;258终点判定条件;47变化量){
36执行好多代码;
}
这三个条件不是必须都在括号里,将初始值放在外边,会使循环的生命周期更长一点
public class A{
public static void main(String[] args){
for(int round=1;round<=5;round++){
System.out.println("跑到第"+round+"圈啦");
}
//循环执行完毕的时候,round=6
System.out.println("循环执行完毕"+round);
//但是运行结果却显示错误:找不到符号,变量round未找到。
}
}
这个就涉及到了变量的生命周期问题,变量是栈内存中开辟的一块空间,从生命开始创建出来,用完就回收了。因为for循环允许将这三个条件放进括号,所以应该这样:
public class A{
public static void main(String[] args){
int round=1;
for(;round<=5;round++){//;不能省略
System.out.println("跑到第"+round+"圈啦");
}
//循环执行完毕的时候,round=6
System.out.println("循环执行完毕"+round);
//运行结果显示:round=6
}
}
所以round=1;放在上边放在下边对循环的整个执行没有影响,生命周期却得到了扩充。
public class A{
public static void main(String[] args){
int round=1;
for( ;round<=5; ){//;不能省略
round++;//这样的话输出的时候第一次是跑到了第2圈,然后是3,4,5,6
System.out.println("跑到第"+round+"圈啦");
}
//循环执行完毕的时候,round=6
System.out.println("循环执行完毕"+round);
//运行结果显示:round=6
}
}
double Math.pow(double a,double b);//计算a的b次方的方法
循环嵌套
import java.util.Scanner;
public class DrawStar{//画*,行数也是每行*的个数
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请您输入*的行数:");
int count = input.nextInt();
for(int i=1;i<=count;i++){//i控制的是*的行数
for(int j=1;j<=count;j++){//j控制的是每一行*的个数
System.out.print("*");
}
System.out.println();
}//这是个双层嵌套循环,执行的次数是内外层循环次数的乘积
}
}
//运行结果:
4
****
****
****
****
import java.util.Scanner;
public class DrawStar{//画*
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请您输入*的行数:");
int count = input.nextInt();
for(int i=1;i<=count;i++){//i控制的是*的行数
for(int j=1;j<=i;j++){//j控制的是每一行*的个数
System.out.print("*");
}
System.out.println();//换行
}//这是个双层嵌套循环,执行的次数是内外层循环次数的乘积
}
}
//运行结果:
4
*
**
***
****
import java.util.Scanner;
public class DrawStar{//画*
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请您输入*的行数:");
int count = input.nextInt();
for(int i=1;i<=count;i++){//i控制的是*的行数
for(int j=1;j<=count-i;j++){//画占位符
System.out.print(" ");
}
//这两个j是可以一样的,因为循环结束会清空内存
for(int j=1;j<=i;j++){//画星星,j控制的是每一行*的个数
System.out.print("*");
}
System.out.println();
}//这是个双层嵌套循环,执行的次数是内外层循环次数的乘积
}
}
//运行结果:
5
*
**
***
****
*****
补充: 转义字符\:可以将\后的一个字符发生转换,可以转换特殊的符号,比如 ’ " \ ,还可以转换特殊的字母,比如 \n(表示换行) \r(表示回车) \t(表示制表符,当做表格来处理或者做一个前面空格的缩进)
比如要想输出helloworld,就这样:System.out.println("helloworld"); ==>helloworld
但是要想输出"helloworld"的话,由于英文里""是不区分左右的,所以计算机会识别错误,所以需要用到转义字符:
System.out.println("\"helloworld\""); ==>"helloworld" System.out.println("hello\nworld"); ==>hello world System.out.println("helloworld"); ==>hello world
for循环
- for(1初始值;258终点判定条件;47变化量){
36执行好多代码;
}
这三个条件不是必须都在括号里,将初始值放在外边,会使循环的生命周期更长一点
1初始值;
for(;258终点判定条件;){
36执行好多代码;
47变化量;
}
break:终止循环
continue:终止这一次的循环,继续执行下面的循环
while循环
先判断再执行,条件不满足就不执行了
初始值;
while(终点判定条件){//只允许写一个终点判定条件
执行好多代码;
变化量;//在上在下的顺序对程序执行的结果是不一样的
}
do…while循环
先执行再判断,条件不满足的话,至少还可以执行一次
初始值;
do{
执行好多代码;
变化量;//在上在下的顺序对程序执行的结果是不一样的
}while(终点判定条件)
==========================================
数组
- 数组是一组数据类型相同的数据的组合,将这些数据统一管理起来。
- 数组本身是一个引用数据类型,数组内存储的类型可以是基本类型,也可以是引用类型。
##数组的定义(声明) - 数据类型[] 数组名字;
int[] x;
char[] y;
boolean[] z;
String[] m;
此外,数组的声明有三种写法:
int[] x;—>更规范
int x[];
int []x;
数组的赋值(初始化)
- 静态初始化
有长度,有元素内容
int[] array = new int[]{10,20,30,40,50};
也可以写为:
int[] array = {10,20,30,40,50}
还可以写为:
int[] array;
若干行代码;
array = new int[]{}; - 动态初始化
有长度,没有元素,并不是真的没有元素,是默认值
int[] array = new int[5];
整数默认值----0
浮点数默认值----0.0
字符型默认值----0对应的char值 97-a 65-A 48-‘0’
布尔型默认值----false
引用数据类型默认值----null
数组元素的访问
存值、取值
- 通过元素在数组中的位置index索引(下标)来访问.
array[index]; - 索引是有范围的,index索引从 0 开始到 数组的长度减一 结束。
[0,数组长度-1]
如果数组索引超出数组范围的话,会出现异常:Array Index OutOf Bounds Exception----数组索引越界
比如:
public class TestArray{
public static void main(String[] args){
int[] array = new int[]{10,20,30,40,50};
//从数组内取得某一个位置的元素
//int value = arrray[4];
//System.out.println(value);
//向数组内的某一个位置存入元素
//array[3] = 400;
//将数组中的每个元素都取出来
//正常的for循环
for(int index=0;index<5;index++){
int value = array[index];
System.out.println(value);
}//数组的遍历
//加强的for循环
for(int value:array){
System.out.println(value);
}//数组的遍历
}
}
数组元素的遍历(轮询)
-
通过循环的方式访问数组的每一个元素 for循环、while循环
-
正常的for循环
for( ; ; ){
}
有三个必要条件
通过index直接访问数组的某一个位置,存取值都行
不好在于写法相对麻烦 -
JDK1.5版本之后,出现了一个新的特性,叫增强for循环(加强for循环,forEach)
for(自己定义的变量(接收数组内的每一个元素):要进行循环的数组名(遍历的数组array)){
}
增强的for循环有两个条件:用来取值的变量,用来遍历的数组,没有index索引
写法相对容易,但是只能取值,不能存值,没有index索引,找不到元素到底是哪个一个
基本类型和引用类型在数组结构上的区别
- 所有的变量空间都存储在栈内存
- 变量空间可以存储基本数据类型,也可以存储引用数据类型
- 存储基本数据类型的变量空间存储的是值,传递的就是值,一个变量改变的话,另一个不变
- 存储引用数据类型的变量空间存储的是地址(引用),传递的就是引用,一个变量地址对应的值改变,另一个就跟着改变
public class TestArray{
public static void main(String[] args){
int a=10;
int b=a;
b=100;
System.out.println(a);//? 10
int[] x = new int[]{10,20,30};
//变量是栈内存中的一个小容器,类型定义了只能存这种东西,这个容器中只能存一份(一个值)
//见到new关键字,相当于在堆内存中申请开辟一块新的空间
//数组在堆内存中的空间形态,是一串连续的地址
int[] y=x;
y[0] = 100;
System.out.println(x[0]);//? 100
}
}
创建一个数组,存储1-100之间的偶数:
public class SaveNumber{
public static void main(String[] args){
//1.首先要创建一个数组
int[] array = new int[50];
//2.需要将1-100之间的偶数存到数组里边
for(int i=0;i<array.length;i++){
array[i] = 2*i+2;
}
//3.输出验证看是否存入正确
for(int v:array){
System.out.println(v);
}
}
}
ps: 在这段代码中,创建数组用的是动态初始化的形式。当元素的个数比较少的时候用静态初始化,当元素的个数很多且有规律,用动态初始化。元素很多且没规律用静态。
总结:
1.数组本身是一个引用数据类型
2.数组是在堆内存中的一串连续的地址存在
3.堆内存的数组空间长度一旦确定,就不能再次发生改变
4.栈内存的变量中存储的是数组的地址引用
5.数组内部存储的类型可以是基本数据类型,也可以是引用数据类型