【java基础】Java基础语法-程序流程控制、函数、数组!

2024-01-03 06:18

本文主要是介绍【java基础】Java基础语法-程序流程控制、函数、数组!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

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


小伙伴们在程序猿的学习和工作过程中,难免会遇到一些磕磕碰碰的问题,难以解决,这些问题可能会困扰你许久,但是懂得人一下就解决了,为此我特意建了一个java学习群,快来加入我们吧:925050116,里面有大量优质视频资料免费领取喔,让你少走弯路,互相学习交流,一起进步,不负年华!!!

你的支持,是我们努力下去的动力!!!


1.程序流程控制

判断结构

三种格式:

 

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

注意:

  • if语句后若未写大括号,那就只能控制离它最近的单条语句。

  • if else与三元运算符的区别在于:三元运算符由于是运算符,因此必须有结果。

  • Java语言中语句一般有两种结束方式:以分号;或后大括号}结束,以}结束的一般为流程控制语句。

  • Example1:if语句无控制体的情况

    if(false);
    {System.out.println("Hello World!");  //会打印Hello World!,实际上if没有控制体,大括号内容叫做局部代码块
    }
    

    Example2:局部代码块

    {int m = 89;System.out.println("Hello World!..."+m);
    }
    System.out.println("Over..."+m);        //编译报错
    

    局部代码块一执行完,m变量在内存中就会被释放,因此局部代码块可以定义局部变量的生命周期。为了节约内存空间,在确保后面不会在使用此变量的情况下,可以使用局部代码块的形式,执行完后,其空间就会被腾出来(虚拟机在内存当中开辟的空间是有限的,除非在启动虚拟机的时候设置需要的空间)。

选择结构

格式:

 

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

特点:

  • switch能判断的数据类型有限,只有四种:byte, short, int, char(Java1.5 为switch增加了枚举类型,Java1.7 增加了字符串类型)。

  • 程序一执行到switch,会把大括号内所有的语句加载到内存中。

  • switch中条件放置无顺序,但执行有顺序。
    Example1:即使default放在第一位,也会先判断case

    switch(表达式)
    {default:执行语句;break;case 取值1:执行语句;break;case 取值2:执行语句;break; ...
    }
    
  • 程序遇到满足条件的值后,如果没有break,则会继续向下执行,之后的case不再进行判断,直接执行里面的语句,直到遇到break或执行到大括号终结。
    Example2

    int x = 2;
    swtich(x)
    {default:System.out.println("d");//break;case 4:System.out.println("a");//break; case 1:System.out.println("b");break;case 3:System.out.println("c");break;
    }
    //输出结果为d, a, b
    
  • Example3:多个值,对应相同执行语句

    int month = 3;
    switch(month)
    {case 3:case 4:System.out.println(month+"月对应的是春季");break;
    }
    

    执行到case 3,满足条件,但没有执行语句和break,继续往下执行并且不判断,执行完case 4中的语句再break

ifswtich的应用:

  • if
    1. 对具体的值进行判断
    2. 对值的区间进行判断
    3. 对运算结果是boolean类型的表达式进行判断
  • switch
    1. 对具体的值进行判断
    2. 值的个数通常是固定的

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

循环结构

三种格式:

 

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

特点:

  • do while:无论条件是否满足,循环体至少执行一次。

  • for的三个表达式运行顺序:初始化表达式只执行一次;判断循环条件,为真就执行循环体,再执行循环后的操作表达式,接着继续判断循环条件,重复整个过程,直到条件不满足为止。

  • whilefor可以互换,区别在于for为了循环而定义的变量在for循环结束就在内存中释放,而while循环使用的变量在循环结束后还可以继续使用。

  • 最简单无限循环格式:while(true)for(;;),无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环(for两边的表达式可以不写,中间不写会默认为true)。

  • Example1:while语句错误写法

    while(条件表达式);  //while语句后加分号,会一直循环
    {执行语句;
    }
    
  • Example2: for第一和第三个表达式的非常规写法

    int x = 1;
    for(System.out.println("a");x<3;System.out.println("c"))
    {System.out.println("d");x++;
    }
    //输出 a d c d c
    //注意能执行成功,只要满足表达式的条件即可
    

应用:
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();
}

输出结果为

常用转义符:

  • n:回车

  • t:制表符

  • b:退格

  • r:按下回车键
    windows系统中回车符其实是由rn这两个符号组成的,linux中回车符是n,dos可以识别nrn,但是windows的一些软件中只能识别rn
    Example4:打印带双引号的hello world

    System.out.println(""hello world"");//错误写法,会识别成前两个双引号为一对
    System.out.println("\"hello world\"");//正确写法
    

    Example5:打印带反斜杠的hello world

    System.out.println("\\hello world");
    

其他流程控制语句

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

注意:

  • 这两个语句离开应用范围就无意义。

  • 这两个语句单独存在下面都不可以有语句,因为执行不到。

  • 如果出现了循环嵌套,break要跳出指定循环,可以通过标号实现——标号的出现,可以让这两个语句作用于指定的范围(标号用得并不多)。
    Example

    xiaoqiang:for(int x=0; x<3; x++)
    {wangcai:for(int y=0; y<4; y++){System.our.println("x=" + x);break xiaoqiang;}
    }
    xiaoqiang:for(int x=0; x<3; x++)
    {wangcai:for(int y=0; y<4; y++){System.our.println("x=" + x);continue xiaoqiang;}
    }
    

2.函数

函数的定义

什么是函数?

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

函数的格式:

 

修饰符 返回值类型 函数名(参数类型 形式参数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修饰符(注意是在编译过程中失败)。

函数的特点

  • 定义函数可以将功能代码进行封装
  • 便于对该功能进行复用,函数的出现提高了代码的复用性
  • 函数只有被调用才会被执行
  • 对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写

注意:

  • 函数中只能调用函数,不可以在函数内部定义函数。
  • 定义函数时,函数的结果应该返回给调用者,交由调用者处理。
    Example

 

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);
}

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

函数调用

栈的形式

 

3.数组

数组的定义

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

好处:可以自动给数组中的元素从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内存分为五片:

  • 寄存器(CPU使用)
  • 本地方法区(调用系统底层内容)
  • 方法区(别名【数据区、共享区、share data】,存储方法)
  • 栈内存(基本数据类型):存储的都是局部变量,变量所属的作用域一旦结束,该变量就会自动释放。
  • 堆内存(引用数据类 ):存储数组和对象(其实数组也是对象),凡是new建立的对象都在堆中。

堆的特点:

  • 每一个实体都有首地址值。
  • 堆内存中的每一个变量都有默认初始化值,根据类型的不同而不一样,整数:0,小数:0.0或者0.0f,boolean:false,char :‘u0000’,实体:null。
  • 垃圾回收机制:当堆中的实体没有被任何变量指向时,不像栈一样,会立刻被释放,而是会被视作垃圾,被自动回收,垃圾回收机制会不定时的,自动检测堆里的垃圾,进行回收。C++需要程序员手动回收堆里的垃圾,析构函数。

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;elsereturn 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'));elseSystem.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];

  • 定义了名称为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,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]); //0int[][] 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的一维数组的长度。

 

这篇关于【java基础】Java基础语法-程序流程控制、函数、数组!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/564759

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>