毕向东Java基础教程-Java基础语法【下】

2019-12-17  本文已影响0人  Lois_Huang

本篇为Java基础语法【下】,包含程序流程控制、函数、数组这三部分内容。


程序流程控制

顺序结构

判断结构

三种格式:

/*=======第一种格式=======*/
if(条件表达式)
{
    执行语句;
}

/*=======第二种格式=======*/
if(条件表达式)
{
    执行语句;
}
else
{
    执行语句;
}

/*=======第三种格式=======*/
if(条件表达式)
{
    执行语句;
}
else if(条件表达式)
{
    执行语句;
}
...
else
{
    执行语句;
}

注意:

选择结构

格式:

switch(表达式)
{
    case 取值1:
        执行语句;
        break;
    case 取值2:
        执行语句;
        break; 
    ...
    default:
        执行语句;
        break;
}

特点:

ifswtich的应用:

对于几个固定的值判断,建议使用switch语句,因为其会将具体的答案都加载进内存,效率相对高一点。
常用的为if,不建议用switch语句,因为其功能性较差,且书写麻烦。

循环结构

三种格式:

/*=======while语句格式=======*/
while(条件表达式)
{
    执行语句;
}

/*=======do while语句格式=======*/
do
{
    执行语句;
}while(条件表达式);

/*=======for语句格式=======*/
for(初始化表达式;循环条件表达式;循环后的操作表达式)
{
    执行语句;(循环体)
}

特点:

应用:
Example3: 打印九九乘法表

for(int x = 1; x <= 9; x++)
{
    for(int y = 1; y <= x; y++)
    {
        System.out.print(y + "*" + x + "=" + y * x + "\t"); // "\t":制表符,可以用来对齐
    }
    System.out.println();
}

输出结果为

常用转义符:

其他流程控制语句

break(跳出):应用于选择结构(swtich)和循环结构(loop)
contine(继续):应用于循环结构(loop)

注意:

函数

函数的定义

什么是函数?

函数的格式:

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

Example

class FunctionDemo
{
    public static void main(String[] args)
    {
        int c = add(3,4);
        System.out.println("c="+c);
    }
    int add(int a, int b)
    {
        return a+b;
    }
}

编译报错:无法从静态上下文中引用非静态方法add(int, int),需要在add()函数前加static修饰符(注意是在编译过程中失败)。

函数的特点

注意:

class Demo 
{
    public static void main(String[] args) 
    {
        System.out.println(add(3,5));
    }
    public static void add(int a, int b)
    {
        System.out.println(a + b);
        return;
    }
}

编译出错: System.out.println(add(3,5));此处不允许使用void类型。

函数的应用

Example:判断成绩所属的等级

public static char getLevel1(int num)
{
    char level;
    if(num>=90 && num<=100) level = 'A';
    else if(num>=80 && num<=89) level = 'B';
    else if(num>=70 && num<=79) level = 'C';
    else if(num>=60 && num<=69) level = 'D';
    else if(num<60) level = 'E';
    return level;
}

public static char getLevel2(int num)
{
    char level;
    if(num>=90 && num<=100) level = 'A';
    else if(num>=80 && num<=89) level = 'B';
    else if(num>=70 && num<=79) level = 'C';
    else if(num>=60 && num<=69) level = 'D';
    else if(num<60 || num>100) level = 'E';
    return level;
}

两个函数均编译错误 :可能尚未初始化变量level;编译时不会判断数值(即使涵盖了所有的情况),只管语法错误,所以最后应加else语句。

函数的重载(overload)

重载的概念:在同一类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。
重载的特点:与返回值类型无关,只看参数列表。
重载的好处:方便于阅读,优化了程序设计(函数的功能一样,仅仅是参与运算的未知内容不同时,可以定义多函数,却使用统一函数名称,这样方便阅读,在调用时,虚拟机通过参数列表的不同来区分同名函数)。

Example1

public static int add(int a, int b)
{
    return a+b;
}
public static double add(int a, int b)
{
    return a+b;
}

编译报错:已在XX中定义add(int, int)…,Java是严谨性语言,如果函数出现调用的不确定性,会编译失败。

Example2:打印乘法表

/**
打印指定参数的任意乘法表
*/
public static void printCFB(int num)
{
    for(int x=1; x<=num; x++)
    {
        for(int y=1; y<=x; y++)
        {
            System.our.print(y+"*"+x+"="+y*x+"t");
        }
        System.out.println();
    }
}
/**
打印标准乘法表(不指定参数的情况下)
*/
public static void printCFB()
{
    for(int x=1; x<=9; x++)
    {
        for(int y=1; y<=x; y++)
        {
            System.our.print(y+"*"+x+"="+y*x+"t");
        }
        System.out.println();
    }
}

如上,一般只要一重载,代码就会重复;可以通过调用的方式,减少重复代码。


/**
打印指定参数的任意乘法表
*/
public static void printCFB(int num)
{
    for(int x=1; x<=num; x++)
    {
        for(int y=1; y<=x; y++)
        {
            System.our.print(y+"*"+x+"="+y*x+"t");
        }
        System.out.println();
    }
}
/**
打印标准乘法表。
*/
public static void printCFB()
{
    printCFB(9);
}

一般由于参数个数的原因重载,都能复用;而如果是参数类型,则不行。

函数调用

栈的形式

数组

数组的定义

概念:同一类型数据的集合,其实数组就是一个容器。

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

格式:

/*=======第一种格式=======*/
元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
/*=========示例========*/
int[] arr = new int[5];

/*=======第二种格式=======*/
元素类型[] 数组名 = new 元素类型[]{元素1, 元素2, ...};
/*=========示例========*/
int[] arr = new int[]{3,5,1,7};   //用new,常规初始化方式
int[] arr = {3,5,1,7};            //静态初始化方式
//以上两种方式在大部分情况下都是通用的,但它们在重新赋值或传参时会有一点小差别

Example

int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
//均输出0(默认赋值为0)

数组的内存分配及特点

Java内存分为五片:

堆的特点:

Example1

int[] arr = new int[3];
//arr在栈中,new int[3]在堆中,堆中存的是实体,实体的用途:用于封装数据,存储很多数据

Example2

sytem.out.print(arr[0]);//先找arr,再根据地址找数组,找到数组后找对应的元素
arr = null;             //让arr不指向任何实体对象 

数组操作常见问题

Example1:ArrayIndexOutOfBoundsException异常

int[] arr = new int[3];
System.out.println(arr[3]);

编译完,不会出错,因为编译时不会在内存中建立数组,因此也不会找角标
运行时,产生问题,当访问到数组中不存在的角标/索引时,就会产生ArrayIndexOutOfBoundsException异常。

Example2:NullPointerException异常

int[] arr = new int[3];
arr = null;
System.out.println(arr[0]);

运行出错,当引用型变量没有任何实体指向时,还在用其操作实体,就会产生NullPointerException异常。

Example3

int[] arr = new int[3];
System.out.println(arr);  //[I@c17164

@右边:哈希值,哈希本身是一种算法,由这个算法来定义数组实体在内存中存储的位置,可以简单理解为是一个地址值,windows支持的,Java调用。
@左边:代表实体的类型, [:数组型, I:int型。
测试的时候用,当我们不知道这个变量接收的数据是什么类型时,可以打印出来看看。

数组常见操作

Example1:获取最值(最大值,最小值)

class Demo
{
    public static void main(String[] args)
    {
        int[] arr = {-34,-19,-11,-109,-3,-56};
        int max = getMax(arr);
        System.out.println("max="+max);
    }
    public static int getMax(int[] arr)
    {
        int max = arr[0];
        for(int x=1; x<arr.length; x++)
        {
            if(arr[x]>max) max = arr[x];
        }
        return max;
    }
}

注意max初始化的问题,若初始化为0,则判断不出最大值。

Example2-1:选择排序,特定位置和其他位置比较

public static void selectSort(int[] arr)
{
    for(int i = 0; i < arr.length-1; i++)
    {
        for(int j = i+1; j < arr.length; j++)
        {
            if(arr[i]>arr[j])
            {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}
//性能问题
//在selectSort中,每次把最小的元素放到固定位置的过程中,会进行大量元素的交换,实际上只要找到值最小的元素,再与固定位置交换即可
public static void selectSort_2(int[] arr)
{
    for(int x=0; x<arr.length-1; x++)
    {
        int num = arr[x];
        int idex = x;
        for(int y=x+1; y<arr.length; y++)
        {
            if(num>arr[y])
            {
                num = arr[y];
                index = y;
            }
        }
        if(index!=x)
        {
            int temp = arr[x];
            arr[x] = arr[index];
            arr[index] = temp;
        }      
    }
}

Example2-2:冒泡排序,相邻元素比较

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++)//-1避免角标越界,-x外循环增加一次,比较的元素个数递减
        {
            if(arr[y]>arr[y+1])
            {
                int temp = arr[y];
                arr[y] = arr[y+1];
                arr[y+1] = temp;
            }
        }
    }
}
//数组中元素的交换可以提取出来,写作函数
public static void swap(int[] arr,int a,int b)
{
    int temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;
}
public static void bubbleSort_2(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);
        }
    }
}
//其中的for循环也可以写成以下形式
for(int x=arr.length-1; x>0; x--)
{
    for(int y=0; y<x; y++)
    {
        ...
    }
}

注意:
1、可以通过调用Arrays.sort(arr);实现排序功能
2、操作的是同一空间

Example3:折半查找(二分查找)

public static int func(int[] arr, int value)
{
    int min, max, mid;
    min = 0;
    max = arr.length;
    mid = (min+max)/2;
    while(min <= max)
    {
        mid = (min+max)/2;//mid = (a+b)>>2;
        if(arr[mid] < value)
            min = mid+1;
        else if(arr[mid] > value)
            max = mid-1;
        else
            return mid;
    }
    return -1;
}

注意:

  1. 给定一个有序数组,若往该数组中存储一个元素,并保证数组仍然是有序的,那么这个元素存储的角标如何获取-->return min。

  2. int[] arr = {13,15,19,27,33,45,78,106};
    Arrays.binarySearch(arr,45);
    //若元素存在,返回元素所在的位置;
    //若元素不存在,返回的是-插入点-1;之所以-1,是因为避免返回0,例如Arrays.binarySearch(arr,5)
    

Example4:进制转换:利用与运算实现

public static void main(String[] args)
{
    toHex(60);
}
//0,1,2,3,4,5,6,7,8,9,A, B, C, D, E, F
//0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
public static void toHex(int num)
{
    for(int x = 0; x < 8; x++)
    {
        int temp = num & 15;
        if(temp > 9)
            System.out.print((char)(temp-10+'A'));
        else
            System.out.print(temp);
        num = num >>> 4;
    }
}
/*
什么时候使用数组呢?
如果数据出现了对应关系,而且对应关系的一方是有序的数字编号,可作为角标使用。

将这些数据存储到数组中,根据运算的结果作为角标直接去查数组中对应的元素即可。
这种方式:称为查表法。
(存在对应关系,但无序,可以使用map)
*/
public static void toHex_2(int num)
{
    if(num == 0)
    {
        System.out.print("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 = num & 15;
        arr[--pos] = chs[temp];
        num = num >>> 4;
    }
    for(int x = pos; x < arr.length; x++)
    {
        System.out.print(arr[x]);
    }
}
/*十进制转二进制/八进制类似
可以通过函数调用的方式,将通用的代码抽出来
*/
//十进制-->十六进制
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.print("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];
    int pos = arr.length;
    while(num != 0)
    {
        int temp = num & base;
        arr[--pos] = chs[temp];
        num = num >>> offset;
    }
    for(int x = pos; x < arr.length; x++)
    {
        System.out.print(arr[x]);
    }
}

注意:可以通过Integer类的方法直接将十进制数转换为对应的进制数

System.out.println(Integer.toBinaryString(-6));
System.out.println(Integer.toHexString(5));
System.out.println(Integer.toOctalString(32));

二维数组

格式:

格式1:int[][] arr = new int[3][2];

格式2:int[][] arr = new int[3][];

格式3:

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

还可以写成如下方式:

int[][] arr = new int[3][2];
int[] arr[] = new int[3][2];
int arr[][] = new int[3][2];

内存图示:

Example1:直接打印二维数组

int[][] arr1 = new int[3][2];
System.out.println(arr);       //[[I@c17164
System.out.println(arr[0]);    //[I@1fb8ee3
System.out.println(arr[0][0]); //0

int[][] arr2 = new int[3][];
System.out.println(arr);       //[[I@c17164
System.out.println(arr[0]);    //null
System.out.println(arr[0][0]); //NullPointerException

Example2:数组长度

System.out.println(arr.length);    //打印二维数组的长度-->就是一维数组的个数。
System.out.println(arr[1].length); //打印二维数组中角标为1的一维数组的长度。
上一篇下一篇

猜你喜欢

热点阅读