-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
java语法基础
Java语言基础由关键字、标识符、注释、常量和变量、运算符、语句、函数和数组等组成。
1、关键字
被Java语言赋予了特殊含义的单词,关键字中所有字母都为小写。
2、标识符
在程序中自定义的一些名称。由26个英文字母大小写,数字:0-9,符号:_、$组成。
(1)定义合法标识符规则:
1.由26个英文字母大小写、0-9数字、_和$符号组成
2.数字不可以开头
3.不可以使用关键字
Java中严格区分大小写。在起名字的时,为了提高阅读性,要尽量有意义。
(2)、Java中的名称规范:
包名:多单词组成时所有字母都小写。
如: xxxyyyzzz 类名
接口名:多单词组成时,所有单词的首字母大写。
如:XxxYyyZzz
变量名和函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写。
如:xxxYyyZzz
常量名:所有字母都大写。多单词时每个单词用下划线连接。
如:XXX_YYY_ZZZ
3、注释
用于注解说明解释程序的文字就是注释。提高了代码的阅读性。
(1).单行注释
格式://注释文字
(2).多行注释
格式:/*注释文字*/
(3).文档注释
格式:/**注释文字*/
注释是一个程序员必须要具有的良好编程习惯。初学者编写程序必须养成习惯:先写注释再写代码。将自己的思想通过注释先整理出来,
再用代码去体现,因为代码仅仅是思想的一种体现形式而已。
4、常量
常量表示不能改变的数值。
(1)、Java中常量的分类:
1. 整数常量:所有整数。
2. 小数常量:所有小数。
3. 布尔(boolean)型常量:只有两个数值,true、false。
4. 字符常量:将一个数字字母或者符号用单引号( ' ' )标识,如:'a'。
5. 字符串常量:将一个或者多个字符用双引号("")标识,如:"hello world"、"a"、""(空字符串)。
6. null常量:只有一个数值就是:null。
5、进制之间的转换
进制的由来
(1)对于整数,有四种表现形式:
二进制:0-1,满2进1。
八进制:0-7,满8进1,用0开头表示,如:012。
十进制:0-9,满10进1。
十六进制:0-9,A-F,满16进1,用0x开头表示。如:0x4A2C。
规律:进制越大,表现形式越短。
(2)、负数的进制:
原理:负数的二进制表现形式就是对应的正数二进制取反加1。
进制转换
1.十进制转成二进制 除以2取余数 。
如:6/2余0,3/2余1,1/2余1,故6的二进制:110。
2.二进制转成十进制 乘以2的幂数 。
如:110=0*2(0)+1*2(1)+1*2(2)=0+2+4=6
3.十进制转八进制 先把十进制转成二进制,然后3个二进制位,代表品1个八进制位 。
如:12的二进制为:1100,3个二进制位表示一个8进制位,不够就在前面补齐0,八进制的表示为:014
4.十进制转十六进制 先把十进制转成二进制,然后4个二进制位,代表1个十六进制位
6、变量
其实就是内存中的开辟一个存储空间,用于存储同一类型常量数据,便于重复使用。
定义变量的格式:
数据类型 变量名 = 初始化值;
例如:int x= 3;
定义变量要明确:类型,名称和初始值。
变量的作用域: 作用域从变量定义的位置开始,到该变量所在的那对大括号结束;
生命周期: 变量从定义的位置开始就在内存中活了;变量到达它所在的作用域的时候就在内存中消失了。
七、Java语言的数据类型
Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存总分配了不同大小的内存空间。
1 byte=1字节=8bit 可表达2的8次方个数字
byte 1个字节 -128---127(27-1)
short 2个字节 -32768---32767
int 4个字节 -65536----65535
long 8个字节
float 4个字节
double 8个字节
char 2个字节
Java语言的数据类型包括8种基本类型,3种引用类型。
类型转换
类型转换共分两种,自动类型转换和强制类型转换。
自动类型转换:
如:byte,short,char之间不会相互转换在计算时都会自动提升为int类型。可以简单的理解成低精度转高精度是自动提升的,高精度转低精度则必须要强制转换。
Boolean类型是不可以转换为其他基本数据类型的。
表达式的数据类型自动提升:
所有的byte型、short型和char的值将被提升到int型。
如果一个操作数是long型,计算结果就是long型;
如果一个操作数是float型,计算结果就是float型;
如果一个操作数是double型,计算结果就是double型。
强制类型转换:把一个容量大的数赋值给一个容量小的数时必须要强制类型转换。
实例:
1、
int x=3;
byte b=5;
x=x+b;//编译正常,byte变量类型自动提升为int。
2、
byte b = 3;
b = (byte)(b + 200);//b与200相加时自动提升为int类型,如果再传值给byte会损失精度,所以要强制转换。
3、
byte b = 1;
b = b += 1; //编译正常, 自带强制转换。b=(byte)(b+1)
4、
byte a=3,b=2;
byte c=a+b;//编译失败。是因为a和b是变量,因为变量的值会变化,不确定具体的值,所以默认使用int类型进行存储。
5、
byte b = 3 + 7;
byte b1 = 3;
byte b2 = 7;
b = b1 + b2;
错误原因:涉及到编译器编译程序时候的细节,之所以byte b = 3 +7;,没有报错,是因为3和7都是常量,编译器知道结果是10,并且在byte范围之内,因此就自动进行了强转,所以不会报错。而b = b1 + b2;中b1和b2都是变量,编译器编译程序是一行一行编译的,它根本不知道b1和b2到底是多少,两个byte类型的数据相加时,首先都会被提升为int类型,他们的和也是int类型,其值可能会超过byte的范围,因此就会报错。
八、运算符
(1)、算术运算符
注:
1.整数与整数相除时,结果永远是整数,小数部分被忽略。
2. 负数对正数取模结果为负数; 正数对负数取模结果为正数。即:运算看左边数字的符号。
如:5%-2=1;-5%2=-1;
(2)、赋值运算符
符号:= , +=, -=, *=, /=, %=
实例:
byte b += 3 与byte b =b+3 的区别
b +=3;//编译器在编译的时候,默认内部进行了强制类型转换,将int转成byte
byte b =b+3;//编译失败,在b+3时类型自动提升为int,再把结果赋值给byte会损失精度。
(3)、比较运算符
1、比较运算符的结果都是boolean型,也就是要么是true,要么是false。
2、比较运算符“==”不能误写成“=”。
(4)、逻辑运算符
逻辑运算符用于连接两个boolean类型的表达式。
规律:
&:只有两边都为true时结果为true,否则为false。
|:只有两边都为false时结果为false,否则为true。
^:两边结果一样,就为false;两边结果不一样,就为true。
&和&&的区别:
&:无论左边结果是什么,右边都得参与运算
&&:如果左边为false,那么右边就不用参与运算了。最终结果为false。
|和||的区别:
|:两边都参与运算。
||:只要左边为true,那么右边不用参与运算。最终结果为true。
异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false。
注:一个数异或同一个数两次,结果还是这个数。如:5^2^2=5。
(5)、位运算符
位运算是直接对二进制位进行运算。
左移几位其实就是该数据乘以2的几次方。
如:3<<2,相当于3*2*2=12
00000000000000000000000000000011
00000000000000000000000000001100
右移几位其实就是该数据除以2的几次幂。
如:6>>1,相当于6/2=3。
(6)、三元运算符
格式:
(条件表达式)?表达式1:表达式2;
如果条件为true,运算后的结果是表达式1;
如果条件为false,运算后的结果是表达式2;
三元运算符两个表达式一定要有个比较的结果,否则无法使用。
如:获取两个整数中的较大的整数。
int a = 3,b = 5;
int max = a > b ? a : b;
九、java语句
(1)、 判断语句
if语句 三种格式:
1.if(条件表达式) { 执行语句; }
2.if(条件表达式) { 执行语句; } else { 执行语句; }
3.if(条件表达式) { 执行语句; } else if (条件表达式) { 执行语句; } …… else { 执行语句; }
如:判断一个数所在的区间
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
if(num>0&&num<=25){
System.out.println("这个0~25的数");
}else if(num>25&&num<=50){
System.out.println("这个25~50的数");
}else if(num>50&&num<=75){
System.out.println("这个50~75的数");
}else {
System.out.println("这个75~100的数");
}
}
}
注:
1.如果if语句中只有一条语句,那么可以不写大括号。
2.如果if语句没写大括号,if就只能控制离它最近的单条语句。
if语句特点:
1.每一种格式都是单条语句。
2.第二种格式与三元运算符的区别:三元运算符运算完要有值出现。好处是:可以写在其他表达式中。
3.条件表达式无论写成什么样子,只看最终的结构是否是true 或者 false。
(2)、选择语句
switch语句格式:
switch(表达式) {
case 取值1:
执行语句;
break;
case 取值2:
执行语句;
break;
……
default:
执行语句;
break;
}
switch语句特点:
1、switch语句选择的类型只有四种:byte,short,int,char。
2、case与default没有顺序。先执行第一个case,没有匹配的case执行default。
3、结束switch语句的两种情况:1.遇到break,2.执行到switch语句结束。
4、如果匹配的case或者default没有对应的break,那么程序会继续向下执行,运行可以执行的语句,直到遇到break或者switch结尾结束。
5、进入switch语句后,执行顺序是先执行case,然后从上到下,最后再执行default。即使default放在case上面,执行顺序也不变。
如:
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
switch(num){
case 1:
System.out.println("a");
break;
case 2:
System.out.println("b");
break;
case 3:
System.out.println("c");
break;
default:
System.out.println("d");
}
}
}
可以多个case同一种处理方式的情况。
如:
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
switch(num){
case 1:
case 2:
case 3:
System.out.println("123");
break;
case 4:
case 5:
case 6:
System.out.println("456");
break;
default:
System.out.println("789");
}
}
}
(3)、循环语句
1.while 循环语句
while语句格式:
while(条件表达式) {
执行语句;
}
2.do while 循环语句
do while语句格式:
do {
执行语句;}while(条件表达式);
do while特点是:无论条件是否满足,循环体至少被执行一次。
3.for循环语句 格式: for(初始化表达式;循环条件表达式;循环后的操作表达式) {
执行语句;
}
for循环特点:
1)、for里面的三个表达式运行的顺序,初始化表达式只读一次,判断循环条件,为真就执行循环体,然后再执行循环后的操作表达式,接着继续判断循环条件,重复找个过程,直到条件不满足为止。
2)、while与for可以互换,区别在于for为了循环而定义的变量在for循环结束就是在内存中释放。而while循环使用的变量在循环结束后还可以继续使用。
3)、最简单无限循环格式:while(true) , for(;;),无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环。
实例:for嵌套打印99乘法表
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
for (int x=1;x<10 ;x++ )//外循环控制行数
{
for (int y=1; y<=x;y++ )//内循环控制每行的个数
{
System.out.print(y+"*"+x+"="+(y*x)+"\t");
}
System.out.println();//换行
}
}
}
(4)、其他流程控制语句
break(跳出), continue(继续)
break语句:应用范围:选择结构和循环结构。
continue语句:应用于循环结构。
注:
1),这两个语句离开应用范围,存在是没有意义的。
2),这个两个语句单独存在下面都不可以有语句,因为执行不到。
3),continue语句是结束本次循环继续下次循环。
4),标号的出现,可以让这两个语句作用于指定的范围。
十、函数
函数就是定义在类中的具有特定功能的一段独立小程序,函数也称为方法。
函数的格式
修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,) {
执行语句;
return 返回值;
}
返回值类型:函数运行后的结果的数据类型。
参数类型:是形式参数的数据类型。
形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。
实际参数:传递给形式参数的具体数值。
return:用于结束函数。
返回值:该值会返回给调用者。
函数的特点
1.定义函数可以将功能代码进行封装
2.便于对该功能进行复用
3.函数只有被调用才会被执行
4.函数的出现提高了代码的复用性
5.对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写。
如:
public class test {
public static void main(String[] args) throws Exception {
count(3,4);
}
public static void count(int a,int b){//没有返回值,写void表示
System.out.println(a+b);
}
public static int add(int c,int d){
return c+d;
}
}
注:
函数中只能调用函数,不可以在函数内部定义函数。 定义函数时,函数的结果应该返回给调用者,交由调用者处理。
(4)、函数的两个明确
明确要定义的功能最后的结果是什么?
明确在定义该功能的过程中,是否需要未知内容参与运算
(5)、函数重载 在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。
重载的特点:与返回值类型无关,只看参数列表。
重载的好处:方便于阅读,优化了程序设计。
函数的功能一样,仅仅是参与运算的未知内容不同时,可以定义多函数,却使用统一函数名称,这样方便阅读。在调用时,虚拟机通过参数列表的不同来区分同名函数。
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
print();
print(3);
}
public static void print(){
print(2);//函数调用
}
public static void print(int num){//函数的重载
System.out.println("hello:"+num);
}
}
十一、数组
(1)、数组的定义
同一种类型数据的集合。其实数组就是一个容器。
(2)、数组的好处可以对该容器中的数据进行编号,从0开始。数组用于封装数据,就是一个具体的实体。
(3)、数组的格式
1.元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
int [] arr=new int[6];
2.元素类型[] 数组名 = new 元素类型[]{元素,元素,……};
int[] arr = {3,5,1,7};
int[] arr = new int[]{3,5,1,7};
(4)、数组内存结构
Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,有对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈内存:
用于存储局部变量,当数据使用完,所占空间会自动释放。
堆内存:
数组和对象,通过new建立的实例都存放在堆内存中。
每一个实体都有内存地址值
实体中的变量都有默认初始化值
实体不在被使用,会在不确定的时间内被垃圾回收器回收
方法区:用来存储方法,静态和共享数据
(5)、数组操作常见问题
1.数组脚标越界异常(ArrayIndexOutOfBoundsException):访问到了数组中的不存在的脚标时发生。
int[] arr = new int[2];
System.out.println(arr[3]);
2.空指针异常(NullPointerException):当引用型变量没有指向任何实体时,用其操作实体,就会发生该异常。
int[] arr = null;
System.out.println(arr[0]);
(6)、数组的常见操作
1、获取最大、最小值
如:获取最大值
package com.heima;
/*
* 思路:定义一个变量来记录每次比较后较大的元素,遍历数组中的元素并与变量中记录的元素比较,最后的结果就是最大值。
* */
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
int[] arr = {2,4,21,45,13,45};
System.out.println(getMax(arr));
}
public static int getMax(int[] arr){
int maxElement = arr[0];
for(int x = 1; x < arr.length; x++){
if(arr[x] > maxElement)
maxElement = arr[x];
}
return maxElement;
}
}
2、排序
有选择排序跟冒泡排序。
如:
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
int[] arr = {2,4,21,45,13,45};
selectSort(arr);
printArray(arr);
}
/*
选择排序。
思路:
1、首先拿数组第一个元素依次与除其自身外的其他每个元素顺序比较,如果第一个元素大于剩下的某个元
素,就互换内容。
2、经过第一轮比较之后,此时,第一个元素就是数组中最小的元素。然后再拿第二个元素与除第一个元素和
其自身的元素进行比较,如果第二个元素大于剩下的某个元素,就互换内容。此时,第二个元素就是数组中倒数
第二小的元素。
3、依次类推,直到最后一个元素。
*/
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;
//swap(arr,x,y);
}
}
}
}
/*
冒泡排序
思路:
1、首先在第一轮排序中,数组从第一个元素到倒数第二个元素依次与其右边的元素进行比较,如果左边的元
素大于右边的元素,那么两个元素就互换。
2、经过第一轮比较,最大的元素就已经存储到数组最右边的结点中了。
3、第二轮排序则是从第一个元素到倒数第三个元素依次与其右边的元素进行比较,如果左边的元素大于右边
的元素,那么两个元素就互换。
4、依照此方式,一直到只有第一和第二个元素互相比较而结束。
*/
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;
}
}
}
}
//打印数组
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0; x<arr.length; x++)
{
if(x!=arr.length-1)
System.out.print(arr[x]+", ");
else
System.out.println(arr[x]+"]");
}
}
}
在真实开发中,JDK中已经提供好了API可以直接供我们调用,Arrays.sort(arr);就可以直接操作数组排序。
3、查找
普通遍历查找、二分查找法
如果一个数组是无序的,那么可以通过简单遍历查找的方式查找到某个元素所在的角标。
package com.heima;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
int[] arr = {2,4,21,45,13,45};
System.out.println(getIndex(arr,13));
}
public static int getIndex(int[] arr, int key){
for(int x = 0; x < arr.length; x++){
if(arr[x] == key)
return x;
}
return -1;
}
}
如果一个数组是有序的,那么就可以通过一种更高效的方式达到相同的目的,也就是二分查找。
思路:
1、设置三个变量记录角标:min、max、mid。min初始值为0,max为数组最大角标,mid为(max+min)/2。
2、查看mid角标的元素是否与待查找的值相等,如果相等,则直接返回角标值,程序终止执行。
3、如果待查找的值小于角标为mid的元素值,那么说明待查找的元素的位置可能在min与mid角标之间。设置max = mid - 1,mid = (max + min)/2,重复第1、2步的操作。
4、如果待查找的值大于角标为mid的元素值,那么说明待查找的元素的位置可能在mid与max角标之间。设置min = mid + 1,mid = (max + min)/2,重复第1、2步的操作。
5、如果数组中不存在待查找的元素,那么按照如上流程,最终min角标值会大于max角标值,此时返回-1。
package com.heima;
import java.util.Arrays;
import java.util.Scanner;
public class test {
public static void main(String[] args) throws Exception {
int[] arr = {2,4,21,45,13,45};
Arrays.sort(arr);//排序
System.out.println(halfSearch(arr,13));
}
//二分查找法
public static int halfSearch(int[] arr,int key){
int min=0,max=arr.length,mid=(min+max)/2;
while (min<=max)
{
mid=(min+max)/2;
if(key>arr[mid]){
min=mid+1;
}
else if (key<arr[mid])
{
max=mid-1;
}
else
return mid;
}
return -1;
}
}
在实际开发中,二分查找也不需要我们自己去写,JDK中已经提供了相关的API供调用。
Arrays.binarySearch(int[] a, int key);
十二、二维数组
二维数组:数组中的数组。二维数组:int[][]。
二维数组的格式
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 = {{3,8,2},{2,7},{9,0,1,6}};
定义一个名称为arr的二维数组
二维数组中的有三个一维数组
每一个一维数组中具体元素也都已初始化
第一个一维数组 arr[0] = {3,8,2};
第二个一维数组 arr[1] = {2,7};
第三个一维数组 arr[2] = {9,0,1,6};
第三个一维数组的长度表示方式:arr[2].length;
实例:求二维数组所有元素的和。
package com.heima;
public class test {
public static void main(String[] args) throws Exception {
int[][] arr={{3,5,2},{3,7},{3,0,1,6}};
System.out.println(getSum(arr));
}
public static int getSum(int[][] arr){
int sum=0;
for (int x=0;x<arr.length ;x++ )//外循环遍历二维数组的长度
{
for (int y=0;y<arr[x].length ;y++ )//内循环遍历每个一维数组的长度
{
sum+=arr[x][y];
}
}
return sum;
}
}