跟着老毕学Java之基础篇(二)

来源:互联网 发布:linux 发送http请求 编辑:程序博客网 时间:2024/06/03 08:43

------- android培训、java培训、期待与您交流! ----------

第二章:Java语言组成

_________________________________________________________

目录:

2.1----关键字

2.2----标示符

2.3----注   释

2.4----常量和变量

2.5----运算符

2.6----语句

2.7----函数

2.8----数组

 

 

 

2.1----关键字
_________________________________________________________

   关键字:被java语言赋予了特殊含义的单词

   特   点:关键字中所有的字母都为小写

《The Java  Language Specification(Third Edition)》对关键字的描述,共有50个关键字。注意:constgoto是保留的关键字。

 

 

2.2----标示符
_________________________________________________________

       标  示  符--------在程序中自定义的一些名称。

       组       成:由26个英文字母大小写,数字:0-9,符号:$_组成。(注意:标示符已经支持中文,但不建议使用,可能会出现不可预知 的错误)

       定义规则:1.不可以数字开头;2.不可以使用关键字

       注      意:Java中严格区分大小写,在起名字时,为提高阅读性,要尽量起有意义的名字。

       命名规范:

                 1.包名:多单词组成时所有字母都小写。e.g.:xxxyyyzzz

                 2.类名接口名:多单词组成时,所有单词的首字母大写。e.g.:XxxYyyZzz

                 3.变量名和函数名:多单词组成时,第一个单词首字母小写,第二 个单词开始每个单词首字母大写。e.g.:xxxYyyZzz

                  4.常量名:所有字母都大写。多单词时每个单词用下划线连接。e.g.:XXX_YYY_ZZZ

 

 

2.3----注   释
_________________________________________________________

 

注释的意义:将代码用现实世界的语言进行解释,以方便理解程序;也用于调试程序,生产文档。

注释的类型:

           1.单行注释://

           2. 多行注释:/*   ……代码…… */

           3.文档注释:/**   ……代码…… */(java特有,可以生产用户使用说明)

注意:1.单行注释可以嵌套在多行注释中,多行注释相互之间不允许嵌套。

           2.写代码一定要养成写注释的习惯。

           3.对于单行和多行注释,被注释的文字,不会被JVM( java虚拟机)解释执行。对于文档注释,是java特有的注释,其中注释内容可以被JDK提供的工具javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。

 

2.4----常量和变量
_________________________________________________________

【常     量】:不能改变的数值,用于给变量赋值。

      分类:1,整数常量。所有整数
                 2,小数常量。所有小数
                 3,布尔型常量。较为特有,只有两个数值。true false。
                 4,字符常量。将一个数字字母或者符号用单引号( ' ' )标识。
                 5,字符串常量。将一个或者多个字符用双引号标识。
                 6,null常量。只有一个数值就是:null。(用于引用数据类型)

      整数的进制:现实世界常用十进制,计算机中多用二进制、八进制和十六进制三种。

      进 制 转 换    

             1、 十进制   转   二进制

             2、二进制转十进制

             3、二进制转八进制、十六进制     

             4、十进制转其他进制(通用的是除法操作,窍门是先转为二进制,再转为八进制和十六进制)

        负数的二进制表现形式:对应的正数二进制取反加1

              

             

【变   量】:

      概念:内存中的一个存储区域;该区域有自己的名称(变量名)和类型(数据类型);该区域的数据可以在同一类型范围内不断变化。

       作用:用来不断存放同一类型的常量,并可以重复使用。

       格式:数据类型  变量名=初始化值;

       注意:变量的作用范围(一对{ }之间有效);初始化值(不能超出范围)

      数据类型:

            Java语言是强类型语言,对于每一个数据类型都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间,并且不随平台的改变而变化。

               

         数据类型转换:分为自动类型转换和强制类型转换

               自动类型转换:也叫隐式类型转换。转换的优先级是double>float>long>int>byte,short,char。byte、short和char是平级的,它们参与运算时都至少先转为int,然后再参与运算。

                强制类型转换:也叫显式类型转换。当把优先级高的数据类型或表达式结果赋值给优先级低的数据类型时,要强转。

                注意:

                1.java是一种强类型定义的语言,强类型定义的语言是指一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用。java、.NET、python、C++等都是强制类型定义的。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。例如你有一个整数,如果不显式地进行转换,你不能将其视为一个字符串。 与其相对应的是弱类型语言:数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。
                2.给一个变量赋值,大体可以分为两类:

                        a----等号右边全是由常量和运算符组成的表达式:因为都是常量,所以虚拟机在编译期就能知道表达式的结果,并判断结果是否在被赋值的变量的类型范围内,如果在则直接赋值,如果不在则需要强制转换。

            byte bt=12;            bt=(byte)139;

                     b-----等号右边有变量参与运算:如果参与运算的变量是byte、short、char,它们会先转变为int类型,再参与运算,类型总是会提升。

 byte b =0;            b=b+b;//这句会报错,为什么?因为b先提升为int了,结果是int。 int m=2147483647;//int的最大值 m=m+m+1;//注意,结果已经超出int范围,但编译器不会报错,它默认自动将结果截取为int类型。     

[小结] 类型转换问题,是初学者最容易迷惑的一块。

2.5----运算符

_________________________________________________________

>算术运算符
>赋值运算符
>比较运算符
>逻辑运算符
>位运算符
>三元运算符

(1)算术运算符(7个)

+   : 正号,加,字符串连接符。

-    : 负号,减。

*    :乘

/    :除(整数处时,结果仍为整数,e.g.:int num=3570;num=num/1000*1000,结果num的值为3000)

 %  :取模(取余数)(注意:结果的正负紧跟左边的符号)

 ++:前自增,后自增

 --:前自减,后自减。

(2)赋值运算符:= , +=, -=, *=, /=, %=(6个)

注意:对于byte x=5;来说,x=x+1,是错误的,需要强制转换;x+=1,x+=1000000却可以直接通过编译。

(3)比较运算符:==,!=,<,>,<=,>=,instanceof(检查是否是类的对象)

注意:比较运算符的结果都是boolean型的,==不能误写成=。

(4)逻辑运算符(6个):用于连接boolean型表达式

   &:与

    |:或

    !:非:

   ^:异或,一真一假则为true,全真或全假则为false(与|的不同是:两边为true时,结果为false)。

&&:与短路,左边为false,则右边不再运算。

| |  :或短路,左边为true,则右边不再运算。

(5)位运算符:主要是二进制运算,是效率最高的。

<<:二进制左移,空位补0,相当于乘以2的n次幂。

>>:带符号右移,最高位是0,则空位补0;最高位是1,则空位补1。

>>>:无符号右移,无论最高位是0还是1,空位都补成0。

&:相应位上都为1,结果才为1。(与上1,7,15,结果相当于取出该数的最低1位、3位和4位,与>>>配合使用,可以取出一个数的所有二进制位。)

| :相应位上只要有一个为1,结果就为1.

^:相应位上不同,结果才为1。(特性:一个数m,连续^n两次,结果仍为m)

~:单元运算符,二进制位上若为0,则变为1;若为1,则变为0。

两个数互换值的三种方法:

public class SwapTest {public static void main(String[] args) {int m = 13,n=15;swap_1(m,n);swap_2(m,n);swap_3(m,n);}//中间变量法public static void swap_1(int m,int n){int temp =m;m=n;n=temp;System.out.println("m="+m+";n="+n);}//求和法:局限性,如果和超出类型取值范围,会出错。  public static void swap_2(int m,int n){int sum =m+n;m=sum-m;n=sum-n;System.out.println("m="+m+";n="+n);}//双异或法public static void swap_3(int m,int n){m=m^n;n=m^n;m=m^n;System.out.println("m="+m+";n="+n);}}

(6)三元运算符(是if  else 语句的一种简写形式,但因为是运算符所以必须有结果)

  格式:
         (条件表达式)?表达式1:表达式2;•
         如果条件为true,运算后的结果是表达式1;
          如果条件为false,运算后的结果是表达式2;
  示例:
     获取两个数中大数。
      int x=3,y=4,z;
      z = (x>y)?x:y;//z变量存储的就是两个数的大数。

拓展:

short d1=0,d2=1;   //这里的short换成其他基本数据类型都可以,    d2=d1<d2?null:d2;这个编译可以通过,但会报空指针异常,如果改成d1>d2,则不会报错;把null换成其他数据类型也会报错。空指针异常是运行时异常,所以编译器不会报错,但运行时如果调用就会出问题。

       

2.6----语句

_________________________________________________________

也可叫做程序流程控制,可大略分为四种结构:顺序结构、判断结构、选择结构、循环结构。

判断结构:if语句

    if语句三种表现形式的执行流程图如下:

选择结构:switch

 switch语句特点:

a,switch语句选择的类型只有四种:byte,short,int ,char。(JDK1.5增加了枚举,JDK1.7支持字符串

b,case之间与default没有顺序。先执行第一个case,没有匹配的case执行default。

c,结束switch语句的两种情况:遇到break,执行到switch语句结束。

d,如果匹配的case或者default没有对应的break,那么程序会继续向下执行,运行可以执行的语句,直到遇到break或者switch结尾结束。

   对于if和switch语句如何选择?

    如果判断的具体数值不读,而且是switch可以选择的类型,建议使用switch,其效率稍高。

     其他情况,如判断区间,表达式结果为boolean类型判断,选择if,if使用范围广泛。(switch能做的if都能做,但switch效率高)

循环结构while ,do while,for

while

格式:

定义初始化表达式;

while(条件表达式){

    循环体(执行语句);

}

do while

格式:

定义初始化表达式;

do{

    循环体(执行语句);

}while(条件表达式)

  注意:do while与while的区别是:do while中循环体至少执行一次。

for

格式:

for(定义初始化表达式;循环条件表达式;循环后的操作表达式){

         循环体(执行语句);

}

注意:for 与while的区别是----for定义的条件控制变量在循环后就不存在了(优化了内存),而while的条件控制变量循环后仍存在。这里涉及变量的生命周期问题:局部变量只在离他最近的一对{ }之间存在。

for语句特点示例:

int b =1,a;for(System.out.println("你好"),b=1,a=0;b<5;b++,a++,System.out.println("好啊")){}


循环流程示意图:

 

【编程思想】  累加     计数器 

拓展:循环的嵌套使用( 打印九九乘法表和金字塔图形)

break和continue关键字循环中的使用示例:

w:for(int x =0;x<4;x++){for(int y=0;y<x;y++){System.out.println(x);//break;//跳出当前循序break w;//通过给循环起名字跳出w标示的循环。//System.out.println(y);//break和continue语句后边的代码都不会被读到,编译报错。}}w:for(int x =0;x<4;x++){for(int y=0;y<x;y++){System.out.println(x);continue w;//跳出当前循序}}


注意:break只能做循环语句和switch语句中使用,continue只能用于循环结构。

           break和continue单独存在时,后边不能有语句,因为读不到,编译器会报错。

           可以通过给循环定义标签的方法,来决定break和continue是作用于那个循环。

 

2.7----函数

_________________________________________________________

什么是函数?

           函数就是定义在类中的具有特定功能的一段独立小程序。也称为方法。

函数的格式是什么?

        修饰符返回值类型函数名(参数类型形式参数1,参数类型形式参数2,)
        {
              执行语句;
             return 返回值;
         }

 

为什么要定义函数?

     程序是为处理数据服务的,如果某些代码实现的是同样的数据操作,比如求和,那么可以将这些代码封装起来,作为一个功能方法来重复调用,以实现代码和功能的复用。

函数有哪些特点?

      实现了代码和功能的封装,提高了功能和代码的复用性,只有被调用时才被执行。没有返回值时,返回值类型用void关键字标示,同时在函数结尾处的return可以省略不写。

怎么定义函数?

  两个明确:明确结果,以确定返回值类型;明确参与运算的未知内容,以确定参数列表。

什么是函数的重载?

重载:在同一个类中,允许一个以上的同名函数存在,只要它们得到参数个数或类型不同。

重载的特点?与返回值类型无关,只看参数列表。重载函数间也可以互相调用。

重载的好处?方便与阅读,优化程序设计。

注意:同一个类中不允许存在只有返回值类型不同的两个同名函数。

 

2.8----数组

_________________________________________________________

 什么是数组?

     同一种类型数据的集合。是容器的一种,它的长度固定。

数组的好处?

       可以自动给数组中的元素从 0 开始编号,以方便对这些元素进行操作。

定义数组的格式是什么?

格式1:元素类型[ ]   数组名 = new 元素类型[ 数组长度];

格式2:元素类型[ ]   数组名 = new 元素类型[ ] { 元素,元素,……,元素};

           或直接写成元素类型[ ]   数组名 =  { 元素,元素,……,元素};

注意:数组长度的最大值为Integer.MAX_VALUE,数组长度在定义时写成负数,编译器不会报错,但运行时会报

           java.lang.NegativeArraySizeException异常。数组是引用类型,期元素在堆内存中会有默认的初始化值。

对数组操作经常碰到的问题有哪些?

主要由两个:空指针异常和数组角标越界异常。

java.lang.ArrayIndexOutOfBoundsException,错误代码如下:

int [] arr1 = new int[12];System.out.println(arr1[12]);


java.lang.NullPointerException,错误代码如下:

byte[] arr2 = null;System.out.println(arr2[0]);

对数组的常见操作有哪些?

常见的有:获取最值、排序(选择排序、冒泡排序)、查找元素角标(二分查找)。示例代码如下:

public class ArrayTest {public static void main(String[] args) {//数组角标越界异常示例;int [] arr1 = new int[12];//System.out.println(arr1[12]);//空指针异常示例byte[] arr2 = null;//System.out.println(arr2[0]);printHorizon();int[] arr ={1,4,6,3,9,14,67,34};//获取最值System.out.println(getMax(arr));printHorizon();//数组排序printArray(arr);//selectSort(arr);//选择排序bubleSort(arr);//冒泡排序printArray(arr);//获取int index =getIndex(arr, 34);//获取元素第一次出现的角标System.out.println(index);int index1 =getInsertIndex(arr, 15);//获取元素插入位置。System.out.println(index1);}//获取最值:public static int  getMax(int[] arr ){int max=0;if(arr!=null){for(int x =0;x<arr.length;x++){if(arr[max]<arr[x]){max=x;}}}return arr[max];}//打印数组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]+"]");}}}//查找数组中某一值第一次出现的位置,若不存在则返回-1;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 binarySearch(int[] arr,int key){int max,mid,min;max =arr.length-1;min=0;mid = (max+min)/2;while(arr[mid]!=key){if(arr[mid]>key){max=mid-1;}else{min=mid+1;}mid=(max+min)/2;if(max<min)return -1;}return mid;}//折半查找第二种方式,以max和min的距离作为循环控制条件public static int binarySearch_2(int[] arr,int key){int max = arr.length-1,min =0,mid;while(max>=min){mid=(max+min)>>1;//斯坦福大学公开课中提出了一点,这句是有bug的,当max+min的和大于int的取值范围时,会出大问题。if(arr[mid]>key){max=mid-1;}else if(arr[mid]<key){min = mid+1;}elsereturn mid;}return -1;}//折半查找的一个变形:获取一个值在一个有序数组中的插入位置。其实就是折半查找后返回min,public static int getInsertIndex(int[] arr,int key){int max = arr.length-1,min =0,mid;while(max>=min){mid=(max+min)>>1;if(arr[mid]>key){max=mid-1;}else if(arr[mid]<key){min = mid+1;}elsereturn mid;}return min;}//选择排序:每次循环后,最值放在最前边。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]){swap(arr, x, y);}}}}//冒泡排序:每次循环后,最值放在最后public static void bubleSort(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])swap(arr,y,y+1);}}}//交换数组中两个元素的位置。public static void swap(int[] arr, int index1,int index2){int temp = arr[index1];arr[index1]= arr[index2];arr[index2]= temp;}public static void printHorizon(){System.out.println("-------------------");}}

 练习:进制转换

public class BaseTrans {public static void main(String[] args) {toBin(60);toHex(60);toOct(60);}//十进制转化成二进制public static void toBin(int num){trans(num, 1, 1);}//十进制转化成八进制public static void toOct(int num){trans(num, 7, 3);}//十进制转化成十六进制public static void toHex(int num){trans(num, 15, 4);}//进制转换抽取出 的方法,以提高复用性public static void trans(int num,int base,int offset){//查表法,定义表char[] chs={'0','1','2','3','4','5','6','7',    '8','9','a','b','c','d','e','f'};//定义一个数组,将每次取出的值,查表后存入该数组中。char[]  res=new char[32];int pos=res.length;//定义指针偏移量,记录从后往前存入数组时,最后一个存入元素的位置。while(num!=0){//有效数字取完则结束循环int temp = num&base;//取最低的offset位的值。res[--pos]=chs[temp];//将值存入结果数组中num =num >>> offset;//无符号右移offset位。}//打印结果for(int x = pos;x<res.length;x++){System.out.print(res[x]);}System.out.println();}}


什么是多维数组?

一个数组的每一个元素又是一个数组,这样的数组就是多维数组。比如int[] []  arr,arr就表示一个二维数组的引用,前边有几个[ ] 维度就是几。

多维数组怎么定义?

多维数组的定义与一维数组一样,以二维数组为例,定义格式如下:

  格式1:

                int [] [] arr = new int[4] [5]; 这表示定义了一个二维数组,它里边有4个一维数组,每个一维数组有5个元素,一维数组的每个元素的初始化值为0。

                int[][]  arr = new int[4] [ ];这个与上边的区别是什么?它也是定义了一个二维数组,它里边也有4个一维数组,但每个一维数组里边有几个元素未定,其初始化值为null(所以不能直接调用以为数组的元素),可以分别对每个一维数组其进行初始化。

格式2:

        int[] [] arr = {{1,2,3},{4,5,6,7},{8,9,10}};

注意:特殊写法,int [] arr,y[ ];此时y是一个二维数组。另外不能这样写:int [] [] arr = new int [ ] [ 4],必须先明确一维数组的个数,然后再明确一维数组每个元素的个数。

 

数组的内存结构是怎么样的?

java中内存分为5部分:寄存器、本地方法区、方法区,栈内存和堆内存。

    其中,栈内存用于存储局部变量,当数据使用完,所占空间会自动释放。

    堆内存用于存储对象和数组,他们通过new 建立的实例都存放在堆内存中。每个实体都有内存地址值,每个引用指向这个地址。当一个实体不被任何引用指向时,堆内存中的垃圾回收机制会不定时的将之自动清除。

数组内存结构示例:

 

一维数组

二维数组

 

 

 

 

------- android培训、java培训、期待与您交流! ----------