1.Java入门
1.1java概述
Java的三种技术架构:
JAVAEE:JavaPlatform Enterprise Edition,开发企业环境下的应用程序,主要针对web程序开发;
JAVASE:JavaPlatform Standard Edition,完成桌面应用程序的开发,是其它两者的基础;
JAVAME:JavaPlatform Micro Edition,开发电子消费产品和嵌入式设备,如手机中的程序;
1.2 Dos命令行
dir:列出当前目录下的文件以及文件夹
md:创建目录
rd:删除目录
cd:进入指定目录
cd..:退回到上一级目录
cd/:退回到根目录
del:删除文件
exit:退出dos命令行
在dos界面内删除文件夹,必须先保证文件夹是空的,可以利用
del 文件夹名 来删除文件夹内的文件
rd 文件夹名 来删除文件夹
del *.txt 表示删除文件夹下所有txt后缀的文件
1.3 java跨平台性
可以通过Java虚拟机(JVM)在系统当中运行,不同系统有不同版本的虚拟机,但java程序不用改变
1.4 Java语言的环境搭建
JRE:Java RuntimeEnvironment,java程序的运行环境,java运行的所需的类库+JVM(java虚拟机)。
JDK:Java Development Kit,java的开发和运行环境,java的开发工具和jre。
配置环境变量:让java jdk\bin目录下的工具,可以在任意目录下运行,原因是,将该工具所在目录告诉了系统,当使用该工具时,由系统帮我们去找指定的目录。
永久配置环境变量方式:
定义java_home的值,利用%java_home%即可动态提取java_home的值,则当java程序目录改变时,只需要变更java_home的值就可以更改环境变量
如下:JAVA_HOME=%安装路径%\Java\jdk
path=%JAVA_HOME%\bin
临时配置环境变量方式:
通过dos命令set,set path就可以看到环境变量path的值,set path= 即可临时定义path的值。如果通过start开启命令符,会继承临时配置的环境变量
特点:系统默认先去当前路径下找要执行的程序,如果没有,再去path中设置的路径下找。
如下:set path=%path%;C:\ProgramFiles\Java\jdk\bin
classpath的配置:
永久配置方式:classpath=.;c:\;e:\
临时配置方式:set classpath=.;c:\;e:\
注意:在定义classpath环境变量时,需要注意的情况
如果没有定义环境变量classpath,java启动jvm后,会在当前目录下查找要运行的类文件;
如果指定了classpath,那么会在指定的目录下查找要运行的类文件。
还会在当前目录找吗?两种情况:
1):如果classpath的值结尾处有分号,在具体路径中没有找到运行的类,会默认在当前目录再找一次。
2):如果classpath的值结尾处没有分号,在具体的路径中没有找到运行的类,不会再当前目录找。
一般不指定分号,如果没有在指定目录下找到要运行的类文件,就报错,这样可以调试程序。
1.5 Java程序开发体验
javac命令,负责的是编译的部分,当执行javac时,会启动java的编译器程序。对指定扩展名的.java文件进行编译。 生成了jvm可以识别的字节码文件。也就是class文件,也就是java的运行程序。
java命令,负责运行的部分.会启动jvm加载运行时所需的类库,并对class文件进行执行。
可以通过set classpath=类所在目录,来临时设置类环境变量,这样可以在任意文件夹中调用编写的类文件,在配置classpath时,结尾不加“;”,加上“;”表示会在目标路径和当前路径下进行寻找
Classpath=.;c:\;d:\ ( . 表示在当前文件夹下寻找)
通过java运行的class文件,优先执行的是环境变量中设置的,比当前文件夹下的类文件更加优先
class 用于定义类,类名通常由单词组成,每个单词首字母大写。用 { }表示类区间
public static voidmain(String[] args) 为固定形式的主函数,其作用在于保证类独立运行
一个文件要被执行,必须要有一个执行的起始点,这个起始点就是main函数
// 单行注释;
/*
*/ 多行注释;
/**
*/ 文档注释;
注释符也可用于程序调试,多行注释中不能插入多行注释
2.Java语言基础组成
2.1关键字
其实就是某种语言赋予了特殊含义的单词。像:this、super、class等,关键字都是小写。
2.2 标识符
Java中的包、类、方法、参数和变量的名字,由任意顺序26个英文字母大小写,数字0-9,符号_$组成,数字不可以开头,不可以使用关键字
16进制需以0x开头
负数的二进制表现形式,就是将正的二进制取反+1,取反即1变0,0变1。负数的最高位都是1。
2.3 变量
变量就是内存中的一个存储空间,用于存储常量数据。
作用:方便于运算。因为有些数据不确定。所以确定该数据的名词和存储空间。
特点:变量空间可以重复使用。
只要数据不确定的时候,就定义变量变量空间的开辟需要的要素有:数据类型、变量名称、变量初始化值。
变量的作用域和生存期:
变量的作用域:
作用域从变量定义的位置开始,到该变量所在的那对大括号结束;
生命周期:
变量从定义的位置开始就在内存中活了;
变量到达它所在的作用域的时候就在内存中消失了;
数据类型:
1)基本数据类型
数值型:整数类型 byte 8 个二进制位表示 -128~127
short 16 个二进制位表示
int 32 个二进制位表示 默认整数类型为这个
long 64 个二进制位表示
浮点类型 float 单精度 定义时需在数字后面加上f
(即小数)double 双精度 默认形式
字符型: char
2)引用数据类型:数组、类、接口
2.4 类型转换
级别从低到高为:byte,char,short(这三个平级)-->int-->float-->long-->double
自动类型转换:从低级别到高级别,系统自动转的;
强制类型转换:什么情况下使用?把一个高级别的数赋给一个别该数的级别低的变量;
byte b =3
b = b +2 将会报错,2默认类型为int,不同类型不能运算
b =(byte) (b + 2) 通过强制转换即可
‘a’+1 其值为98,因为此时会将字符a提升为int型(即97)
字符串数据和任何数据使用+都是相连接,最终都会变成字符串
2.5 算术运算符
%为取模,如1%5=1,5%5=0,6%5=1,-1%5=-1,1%-5=1,正负只取决于左边的数
任何整数模2不是0就是1,所以只要改变被模数就可以实现开关运算。
++为自加,a++ 即 a=a+1
int a = 3,b;
b=a++;
System.out.println(b); → 3
System.out.println(a); → 4
此运算为先将b赋于a的值,a再进行自加
2.6 转义字符
通过\来转变后面字母或符合的含义
\n:换行
\b:退格,相当于backspace
\r:按下回车键,window系统中,回车符是由两个字符来表示\r\n
\t:制表符,相当于tab键
System.out.println("\”Hello\”"); 即可输出带”Hello”
2.7 赋值运算符
= += -= *= /= %=
shorts=4;
s =s+5
上述运算将会报错,因为5为int型,将s+5赋值于s为不同类型的赋值,容易丢失精度
shorts=4;
s+=5
+=属于一个赋值动作,将会自动进行类型转换,因此此运算通过
2.8 逻辑运算符
and → & 两边有一个为false,结果为false
or → | 两边有一个为true,结果为true
异或 → ^ 和|有一些不一样,即true ^ true = false,两边相同,结果为false,两边不同,
结果为true
&&→ (and)短路 当左边为false,右边不运算,结果为false。
|| → (or)短路 当左边为true时,右边不运算,结果为true
2.9 位运算符
<< 左移 3<<2即先将3转换为二进制,再将位数左移,其值为12,3*2*2
>> 右移 6>>2即先将6转换为二进制,再将位数右移,其值为1,6/2/2
>>>无符号右移,>>的最高位如果是1需要补1,而>>>都是补0
& 如6&3,将6和3都转换成二进制,将两者各位进行 & 逻辑运算
| 将两者转换成二进制,再对各位进行 | 逻辑运算
^ 将两者转换成二进制,再对各位进行 ^ 逻辑运算,即取反
将n与m的值进行交换,不通过第三方变量
int n = 3,m = 8;
n = n ^ m;
m = n ^ m; // (n ^ m)^m
n = n ^ m; // (n^m)^n
2.10 三元运算符
(条件表达式)?表达式1:表达式2;
如果条件为true,运算后的结果是表达式1;
如果条件为false,运算后的结果是表达式2;
好处:可以简化if else代码
弊端:因为是一个运算符,所以运算完必须要有一个结果
将给定数字转换为16进制:
int num = 60;
int n1 = mun & 15; //提取num二进制的后四位
n1>9?(char)(n1-10+'A'):n1); //输出提取数字的十六进制形式
/*此处输出结果为67,因为n1为int型,三元运算时会将char型提升为int型*/
int temp = 60 >>> 4; //去除num二进制的后四位
int n2 = temp & 15; //提取第二个四位
System.out.println(n2>9?(char)(n2-10+'A'):n2);
2.11 程序流程控制
1) 判断结构
if else 结构 简写格式: 变量 = (条件表达式)?表达式1:表达式2;
//判断给定数字所属季节:
int x = 4;
if (x>12 || x<1) //先将无效的数字排除
System.out.println(x+"月份不存在");
else if (x>=3 && x<=5)
System.out.println(x+"春季");
else if (x>=6 && x<=8)
System.out.println(x+"夏季");
else if (x>=9 && x<=11)
System.out.println(x+"秋季");
else
System.out.println(x+"冬季");
2) 选择结构
switch语句
switch(表达式)
{
case 取值1:
执行语句;
break;
case 取值2:
执行语句;
break;
……
default:
执行语句;
break;
}
switch的值只包括byte, short ,int,char。case和default的排放顺序随意,但执行顺序是固定的,最后执行default
在switch语句中,String的比较用的是String.equals,因此可以放心的使用。
需要注意的是,传给switch的String变量不能为null,同时switch的case子句中使用的字符串也不能为null。
如果switch传入的null,那么在运行时对一个null对象调用hashCode方法会出现NullPointerException。
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
switch的工作原理:用小括号中的变量的值依次和case后面的值进行对比,和哪个case后面的值相同了,就执行哪个case后面的语句,如果没有相同的则执行default后面的语句;
细节:1):break是可以省略的,如果省略了就一直执行到遇到break为止;
switch后面的小括号中的变量应该是byte,char,short,int四种类型中的一种;
3):default可以写在switch结构中的任意位置;如果将default语句放在了第一行,则不管expression与case中的value是否匹配,程序会从default开始执行直到第一个break出现。
//判断给定数字所属季节:
switch(x)
{
case 3:
case 4:
case 5:
System.out.println(x+"春季");
break;
case 6:
case 7:
case 8:
System.out.println(x+"夏季");
break;
case 9:
case 10:
case 11:
System.out.println(x+"秋季");
break;
case 12:
case 1:
case 2:
System.out.println(x+"冬季");
break;
default:
System.out.println("none");
}
if结构不仅能够判断数值,还能判断区间,而switch结构不好判断区间,而且不能判断boolean型
对于数值确定且不多,且符合byte short int char四种类型宜用switch结构,其他结构宜用if结构
3) 循环结构
1.dowhile 循环
do
{
执行语句;
}
while (表达式);
while语句:先判断条件,只有条件满足才执行循环体
do while语句:先执行循环体,再判断条件,条件满足,再继续执行循环体。无论条件是否满足,循环体至少执行一次
2.for循环
for(初始化表达式;循环条件表达式;循环后的操作表达式)
{
执行语句;
}
例如;
for(int x =0;x<3;x++)
{
System.out.println("x="+x);
}
for循环和while循环的区别:
1.)变量有自己的作用域,对于for来讲,如果将用于控制循环的增量定义在for语句中,那么该变量只在for语句内有效,for语句执行完毕,该变量在内存中被释放
2.)for和while可以进行互换。如果需要定义循环增量,用for更为合适。
当要对某些语句执行很多次时,就使用循环结构。
无限循环的最简单表现形式:
for( ; ; ) { }
while ( true ) { }
break和continue单独存在时,下面不可以有任何语句,因为都执行不到,编译会失败
for (int x=0;x<3 ;x++ )
{
continue; //不会执行下一句
System.out.println("x="+x); //直接跳入下个循环
}
当循环嵌套时,break只跳出当前所在循环。要跳出嵌套中的外部循环,只要给循环起名字即可,这个名字称之为标号。
循环利用实例:
/*
输出图形的代码:
----*
---* *
--* * *
-* * * *
* * * * *
*/
for (int x=0;x<5 ;x++ )
{
for (int y=x+1;y<5 ;y++ )
{
System.out.print("-");
}
for (int z=0;z<=x ;z++ ) //由于打印没有换行,此循环的结果是接在<span style="font-family: Arial, Helvetica, sans-serif;">上一个循环的后面</span>
{
System.out.print("* ");
}
System.out.println();
}
2.12 函数
函数是为了提高代码的复用性,可以将其定义成一个单独的功能,该功能的体现就是java中的函数。
java中函数的定义格式:
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,……)
{
执行语句;
return 返回值;
}
例:
class Function
{
public static void main(String[] args)
{
int x=getResult(4); //利用程序进行计算
System.out.println("x="+x);
}
public static int getResult(int num) //定义的程序
{
return num*3+5;
}
}
对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的
return语句如果在最后一行可以省略不写
如:
public static void getResult(int num)
{
System.out.println(num*3+5); //此处没有具体返回值,返回值类型用void
}
函数中不能定义函数,只能调用函数,返回值类型为void时,不能在打印语句中
如何定义一个函数?
函数其实就是一个功能,定义函数就是实现功能,通过两个明确来完成:
1)、明确该功能的运算完的结果,其实是在明确这个函数的返回值类型。
2)、在实现该功能的过程中是否有未知内容参与了运算,其实就是在明确这个函数的参数列表(参数类型&参数个数)。
函数的作用:
1)、用于定义功能。
2)、用于封装代码提高代码的复用性。
注意:函数中只能调用函数,不能定义函数。
主函数:
1)、保证该类的独立运行。
2)、因为它是程序的入口。
3)、因为它在被jvm调用。
如果函数名称相同,但是参数类型或个数不同,则函数重载,即使参数个数相同,相对应的参数类型如果不同,也属于重载。重载和返回值类型没关系。
void show ( int a,char b, double c) { }
void show ( int x,char y, double z) { } //不重载
int show ( int a,double c, char b) { } //重载
void show ( int a,double c, char b) { } //重载
double show ( int x,char y, double z) { } //这个函数不可以和给定函数同时存在
2.13 数组
数组时用于存储同一类型数据的一个容器。好处:可以对该容器中的数据进行编号,从0开始。数组用于封装数据,就是一个具体的实体。
元素类型[ ] 数组名 = new 元素类型 [元素个数或数组长度]
//new是用来在内存中形成一个容器实体
int [ ]arr = new int [ 5 ]
元素类型[ ] 数组名 = new 元素类型 [ ] { 元素,元素,……}
int [ ]arr = new int [ ] {3,5,1,7}
int [ ]arr = {3,5,1,7}
int [ ] x= new int [3]; int [ ] y = x; y[1] = 89; s.o.p(x[1]); → 89
数组会在堆内存中开辟实体内存,上述x,y都指向此数组,改变y[1]的值就是在改变堆内存中数组的值,指向此数组的x的值也在同时改变。
ArrayIndexOutOfBoundsException:操作数组时,访问到了数组中不存在的角标。
NullPointerException:空指针异常:当引用没有任何指向值为null的情况,该引用还在用于操作实体
数组名称.length = 数组的长度
数组排序实例:
//选择排序
public static void sellectSort(int[] arr)
{
for (int x=0;x<arr.length-1 ; x++) //嵌套循环
{
for (int y=x+1;y<arr.length ;y++ ) //从角标0开始依次与其之后的数进行比较,将最小值排在角标0处
{ //下一次从角标1开始,将第二小值排在角标1处,以此来推进行排序
if (arr[x]>arr[y])
{ int bigger=arr[x];
arr[x]=arr[y];
arr[y]=bigger;
}
}
}
}
//冒泡排序
public static void bubbleSort(int[] arr) //相邻的两个元素进行比较,如果符合条件就换位
{
for (int x=0;x<arr.length-1 ;x++ ) //第一圈:最值出现排在最后
{
for (int y=0;y<arr.length-x-1 ;y++ ) //-x:让每一次比较的元素减少
{ //-1:避免越界
if (arr[y]>arr[y+1])
{
int temp =arr[y];
arr[y] = arr[y+1];
arr[y+1] = temp;
}
}
}
}
无论什么排序,都需要对满足条件的元素进行位置置换。所以可以把这部分相同的代码提取出来,单独封装成一个函数。
Arrays.sort(arr)
折半查找可以提高提高效率,但是必须要保证该数组是有序的数组
public static int halfSearch(int[] arr,int key)
{
int min = 0,max = arr.length-1,mid;
while(min<=max)
{
mid = (max+min)>>1; //右移1位相当于除以2
if(key>arr[mid])
min = mid + 1;
else if(key<arr[mid])
max = mid -1;
else
return mid;
}
return -1;
}
程序的应用实例:十进制转化
public static void trans(int num,int base,int offset)
{
if(num==0)
{
System.out.println(0);
return;
}
char[] chs = { '0','1','2','3', //二进制,八进制,十六进制都适用此表
'4','5','6','7',
'8','9','A','B',
'C','D','E','F' };
char[] arr = new char[32]; //char最高取到32位
int pos = arr.length;
while(num!=0)
{
int temp = num & base; //对应二,八,十六进制,base分别为1,7,15
arr[--pos] = chs[temp];
num = num >>> offset; //对应二,八,十六进制,offset分别为1,3,4
}
for (int x=pos;x<arr.length ;x++ )
{
System.out.print(arr[x]);
}
}
//此程序是通过给定数字,取模的基数(1,7,15),右移的位数(1,3,4),来进行进制转化