Java语言基础
关键字
关键字就是指一些被赋予Java含义的单词。关键字中所有字母都是小写。在起类名的时候规范首字母为大写字母。
用于定义数据类型的关键字: class、interface、byte、short、int、long、float、double、char、boolean、void;
用于定义数据类型值的关键字: true、false、null;
用于定义流程控制的关键字: if、else、switch、case、default、while、do、for、break、continue、return;
用于定义访问权限修饰符的关键字: private、protected、public;
用于定义类与类之间关系的关键字: extends、implements;
用于定义建立实例及引用,判断实例的关键字: new、this、super、instanceof;
用于异常处理的关键字: try、catch、finally、throw、throws;
用于包的关键字: package、import;
其他修饰符关键字: native、strictfp、transient、volatile、assert;
标识符
在程序中自定义一些名称。由26个英文字母大小写,数字0-9,符号_$组成。定义合法标识符规则:1.数字不可以开头;2.不可以使用关键字。Java中严格区分大小写,在起名字时,为了提高阅读行,尽量有意义。
注释
//这里是一行注释
/*
这里是
多行注释
*/
/**
文档注释。文档中写的文档注释可以通过javadoc.exe提取。
可以生成一个说明书。
*/
class Demo{
public static void main(String[] args){
System.out.println("hello world");
}
}
单行注释中可以嵌套单行注释,单行注释可以嵌套多行注释,多行注释可以嵌套单行注释,多行注释不可以嵌套多行注释。注释可以进行程序的调试,要注意不能用多行注释嵌套多行注释。
注释的应用:
开发时要对写的程序写上注释。写程序时第一步先写注释:需求->思路->步骤。
常量和变量
常量
常量即不能改变的数据。
Java中常量的分类:
1.整数常量,所有整数;
2.小数常量,所有小数;
3.布尔(boolean)型常量,较为特有,只有两个数值,true,false;
4.字符常量,将一个数字字母或者符号用单引号(‘ ’)标识;
5.字符串常量,将一个或者多个字符用双引号(“ ”)标识;
6.null常量,只有一个数值就是null;
对于整数有四种表现形式:
1.二进制;
2.八进制;
3.十进制;
4.十六进制;
变量
变量指内存中的一个存储区域,该区域有自己年地名称(变量名)和类型(数据类型),该区域的数据可以在同一类型范围内不断变化。变量可以用来不断的存放同一类型的常量,并且可以重复使用。变量的作用范围为一对{}之间有效,变量定义时应注意初始化值。
变量的定义格式:数据类型 变量名=初始化值;,格式是固定的。变量如同数学中的未知数。
数据类型分为基本数据类型和引用数据类型,基本数据类型分为数值型(整数型:byte,short,int,long;浮点型:float,double)、字符型(char)、布尔型(boolean);引用数据类型分为类(class)、接口(interface)、数组( [] )。整数默认int,小数默认double。
class Demo{
public static void main(String[] args){
//数据类型 变量名=初始化值;
byte b=3; //如果b=300则编译时会报错,会损失精度。3为int型,赋值给一个byte型;
short s=4000;
int x=12;
long l=123l;
float f=1.1f;
double d=2.3;
char ch='a';
boolean bl=true;
bl=false;
System.out.println(b);
}
}
自动类型转换(隐式类型转换);强制类型转换(显式类型转换)。强制转换要慎用,容易丢失精度。
运算符
算术运算符
+(加法运算、连接符),-, *, /,% ,++,- -
赋值运算符
=,+=,-=,*=,/=
如short s=3;
s+=4; //底层会帮忙自动进行强制转换
s = (short)(s+4); //底层不会帮忙进行强制转换,需要手动强制转换;
比较运算符
<,>,==,<=,>=,instanceof
比较运算符运算完的结果是true或者false
逻辑运算符
&,|,^,!,&&,||
用于连接两个boolean类型的表达式
&:无论左边的运算结果是什么,右边都参与运算
&&:当左边为false时,右边不参与运算
|:无论左边的运算结果是什么,右边都参与运算
||:当左边为true时,右边不参与运算
位运算符
<<(左移),>>(右移),>>>(无符号右移),&(位与),|(位或),^(位异或),~(取反)
一个数异或同一个数两次,结果还是这个数
三元运算符
格式:(条件表达式)?表达式1:表达式2;
如果条件为true,运算后的结果是表达式1;
如果条件为false,运算后的结果是表达式2;
三元运算符就是if else语句简写格式;
当if else运算后有一个具体的结果时,可以简化为三元运算符;
语句
程序流程控制
局部代码块
{}内的内容为一个局部代码块
局部代码块可以定义局部变量的生命周期
判断结构
//方法一
if(条件表达式){
执行语句;
}
//方法二
if(条件表达式){
执行语句;
}
else{
执行语句;
}
//方法三
if(条件表达式){
执行语句;
}
else if(条件表达式){
执行语句;
}
...
else{
执行语句;
}
选择结构
//switch语句
switch(表达式){//只有byte,short,int,char这四种类型可供switch选择
case 取值1:
执行语句;
break;
case 取值2:
执行语句;
break;
case 取值3:
执行语句;
break;
...
default:
执行语句;
break;//在switch的最后一个选项上,break可以省略不写
}
if和switch的应用:
if:
1.对具体的值进行判断;
2.对区间判断;
3.对运算结果是boolean类型的表达式进行判断;
switch:
1.对具体的值进行判断;
2.值得个数通常是固定的;
3.对于几个固定的值进行判断,建议使用switch,因为switch语句会将具体的答案都加载进内存,效率高一点;
4.switch语句并不常用;
循环结构
//代表语句:while,do while,for
//while语句格式:
while(条件表达式){
执行语句;
}
//do while语句格式:
do{
执行语句;
}while(条件表达式);
/*
do while的特点:
条件无论是否满足
循环体至少执行一次
*/
for(初始化表达式;循环条件表达式;循环后的操作表达式){
执行语句;(循环体)
}
/*
1.for里面的连个表达式运行的顺序,初始化表达式只读一次,判断循环条件,
为真就执行循环体,然后再执行循环后的操作表达式,接着继续判断循环条件,
重复整个过程,直到条件不满足为止;
2.while与for可以互换,区别在于for为了循环而定义的变量在for循环结束
就是在内存中释放,而while循环使用的变量在循环结束后还可以继续使用;
3.最简单无限循环格式,while(true),for(;;),无限循环存在的原因是并
不知道循环多少次,而是根据某些条件,来控制循环。
*/
for(System.out.println("a");x<3;System.out.println("c")){
System.out.println("d");
}//结果:a d c d c
当对某些代码执行很多次时使用循环结构完成。当对一个条件进行一次判断时,可以使用if语句,当对一个条件进行多次判断时,可以使用while语句。
注意: 在使用循环时,一定要明确哪些语句需要参与循环,哪些不需要。循环通常情况下,需要定义条件,需要控制次数。
语句的嵌套形式:
for(int x=0;x<3;x++){//外循环控制的是行数
for(int y=0;y<4;y++){//内循环控制的是每一行的个数
System.out.println("OK");
}
}
\n:回车
\t :制表符
\b:退格
\r :按下回车键
Windows系统中回车符其实是由两个符号组成的\r \n.
Linux中回车符是\n.
\ :转义字符,对\后面的一个字符进行转义
其它流程控制语句:
break语句:应用范围:选择结构和循环结构;
continue语句:应用于循环结构;
注:
1.这两个语句离开应用范围,存在是没有意义的;
2.这两个语句单独存在下面都不可以有语句,因为执行不到;
3.continue语句是结束本次循环继续下次循环;
4.标号的出现,可以让这两个语句作用于指定的范围;
5.当break语句单独存在时,下面不要定义其他语句,因为执行不到;
6.当continue语句单独存在时,下面不要定义其他语句,因为执行不到;
for1:for(int x=0;x<3;x++){
for2:for(int y=0;y<4;y++){
System.out.println("a");
break for1;//跳出外层循环,此嵌套循环结束;
}
}
函数
函数的定义
函数就是定义在类中的具有特定功能的一段独立小程序,函数也称为方法。
函数的格式:
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,...){
执行语句;
return 返回值;
}
/*
返回值类型:函数运行后的结果的数据类型;
参数类型:是形式参数的数据类型;
形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数;
实际参数:传递给形式参数的具体数值;
return:用于结束函数;
返回值:该函数运算后的结果,该结果会返回给调用者;
*/
特殊情况:功能没有具体的返回值,这是return的后面直接用分号结束,因为没有具体的值,所以不可以写具体的数据类型,在Java中只能用一个关键字来表示这种情况。关键字是void。
总结:没有具体返回值时,返回值类型用void来表示。如果返回值类型是void,那么函数中的return可以省略不写。
函数的特点
定义函数可以将功能代码进行封装,便于对该功能进行复用;函数只有被调用才会被执行;函数的出现提高了代码的复用性;对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写。
注意: 函数中只能调用函数,不可以再函数内部定义函数,定义函数时,函数的结果应该返回给调用者,交由调用者处理。
函数的应用
//9 9 乘法表
public static void print99(){
for(int x=1;x<=9;x++){
for(int y=1;y<=x;y++){
System.out.println(y+"*"+x+"="+y*x+"\t");
}
System.out.println();
}
}
函数内存加载过程
在DOS命令行中运行一个名为FunctionDemo3.java的文件:
/> javac FunctionDemo3.java --> FunctionDemo3.class
/> java FunctionDemo3
javac命令对FunctionDemo.java进行编译,如果编译通过,则会生成字节码文件FunctionDemo3.class文件,这也就是java的运行程序,java命令启动了JVM,当启动JVM之后,会自动寻找main方法,如果没有找到就会报错。也就是说如果没有main方法,编译是可能通过的,但是在运行时会找到错误。
class Function2{
public static int add(int a,int b){
return a+b;
}
public static void main(String[] args){
int x=add(3,5);
System.out.println("x="+x);
}
}
以上述代码为例,虚拟机在启动之后,然后在栈(先进来的放入栈底)内存中划分一部分空间,先分配一个内存存放main方法,执行main函数,执行主函数中的第一句语句;内存中变量x暂时未知,调用add;内存再分配一个存放add的空间,同时把实际参数a和b进行运算;然后把a+b的结果赋给变量x;内存释放add内存;继续执行main函数中的第二名语句进行输出;内存释放main方法的内存。
函数的重载(Overload)
在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可;重载与返回值的类型无关,只看参数列表;重载可以方便阅读,优化了程序设计;Java是严谨性语言,如果函数出现的调用的不确定性,会编译失败。
//重载示例
//返回两个整数的和
int add(int x,int y){
return x+y;
}
//返回三个整数的和
int add(int x,int y,int z){
return x+y+z;
}
//返回两个小数的和
double add(double x,double y){
return x+y;
}
/*
函数起名根据功能而定
add(4,5);
add(2.3,1,1);
用参数列表来区分其不同
*/
重载练习:
//打印乘法表
public static void printCFB(int num){
for(int x=1;x<=num;x++){
for(int y=1;y<=x;y++){
System.out.print(y+"*"+x+"="+y*x+"\t");
}
System.out.println();
}
//打印标准9 9乘法表
public static void printCFB(){
printCFB(9);
}
数组
数组的定义
数组即同一种数据的集合,其实就是一个容器;可以自动给数组中的元素从0开始编号,方便操作这些元素。
格式1:
元素类型[] 数组名=new 元素类型[元素个数或数组长度];
int[] arr=new int [5];
格式2:
元素类型[] 数组名=new 元素类型[]{元素,元素,…};
int[] arr=new int []{3,5,1,7};
int[] arr={3,5,1,7};
数组的内存分配及特点
内存的划分:
1.寄存器;
2.本地方法区;
3.方法区;
4.栈内存:存储的都是局部变量,而且变量所属的作用域一旦结束,该变量就自动释放。
5.堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都在堆中。特点:每一个实体都有一个首地址值;堆内存中的每一个变量都有默认初始化值,根据类型的不同而不同,整数是0,小数是0.0或者0.0f,boolean类型为false,char为’\u0000’;释放方式是垃圾回收机制(与c++有很大的不同)。
数组操作常见问题
public static void main(String[] args){
int[] arr=new int[3];
System.out.println(arr[3]);//运行时会出问题,数组超出范围
//打印实体类型
System.out.println(arr);
arr=null;//指向空指针
System.out.println(arr[0]);//运行时出问题
//当引用型变量没有指向任何实体指向时,还在用其操作实体,就会发生该异常。
}
数组常见操作
对数组操作最基本的动作就是存和取。核心思想:对脚标(索引)的操作。
获取最值(最大值,最小值):
class ArrayDemo{
//定义变量记录较大的值;
public static int getMax(int[] arr){
int maxIndex=0;
for(int x=1;x<arr.length;x++){
if(arr[x]>arr[maxIndex])
maxIndex=x;
}
return arr[maxIndex];
}
}
排序(选择排序,冒泡排序):
class ArrayDemo{
//选择排序;
public static void selectSort(int[] arr){
for(int x=0;x<arr.length-1;x++){
for(int y=x+1;y<arr.length;y++){
if(arr[x]>arr[y]){
int temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
}
}
return ;
}
//冒泡排序
public static void bubbleSort(int[] arr){
for(int x=0;x<arr.length-1;x++){
for(int y=0;y<arr.length-1-x;y++){
if(arr[y]>arr[y+1]){
int temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
}
}
return ;
}
}
折半查找(二分查找):
//普通查找
public static int getIndex(int[] arr,int key){
for(int x=0;x<arr.length;x++){
if(arr[x]==key)
return x;
}
return -1;
}
//二分查找
public static int halfSearch(int[] arr,int key){
int max,min,mid;
min=0;
max=arr.length-1;
mid=(max+min)/2;
while(arr[mid]!=key){
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
if(max<min)
return -1;
mid=(max+min)/2;
}
return mid;
}
//二分查找另解
public static int halfSearch2(int[] arr,int key){
int max,min,mid;
min=0;
max=arr.length-1;
while(min<=max){
mid=(max+min)/2;
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
else return mid;
}
return -1;
}
//Java中的二分查找
/*
如果元素存在,返回元素的索引;
如果元素不存在,返回元素的插入点的相反数-1;
*/
int Index=Arrays.binarySearch(arr,key);
进制转换:
//十进制转十六进制
public static void toHex(int num){
trans(num,15,4);
}
//十进制转二进制
public static void toBinary(int num){
trans(num,1,1);
}
//十进制转八进制
public static void toOctal(int num){
trans(num,7,3);
}
//转换函数
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[8];
int pos=arr.length;
while(num!=0){
int temp=nums&base;
arr[--pos]=chs[temp];
num=num>>>offset;
}
for(int x=pos;x<arr.length;x++)
System.out.println(arr[x]);
System.out.println();
return;
}
二维数组
格式1: int[][] arr=new int[3][2];
定义了名称为arr的二维数组;二维数组中有3个一维数组;每一个一维数组中有2个元素;一维数组的名称分别为arr[0],arr[1],arr[2];给第一个一维数组1脚标位赋值为78写法是:arr[0][1]=78;
格式2: int[][] arr=new int[3][];
二维数组中有3个一维数组;每一个一维数组都是默认初始化值null;可以对这个三个一维数组分别进行初始化:arr[0]=new int[3]; arr[1]=new int[1]; arr[2]=new int[2];
格式3: int[][] arr={{1,2,3},{1,2,3,4],{5,4}};
int[][] arr=new arr[3][2];
int len1=arr.length;//二维数组的长度,其实就是一维数组的个数;
int len2=arr[1].length;//二维数组中脚标为1的一维数组的长度;