流程控制语句
if …else…和三元运算符的区别
共同点:
都是针对两种情况进行判断,都有表达式。
不同点:
if..else...流程控制语句范围比较大,不仅可以操作数据值,还可以输出语句去完成逻辑判断,而三元运算符仅仅是运算符,操作两个具体的数值。
三元运算符能够实现的一定可以使用if...;else...流程语句。
if...else...流程语句实现的,不一定可以使用三元运算符实现。
选择结构之switch
switch(变量名){
case 值1:
语句1;
break ;
case 值2;
语句2;
break ;
....
....
....
default:
语句n;
break ;
}
执行流程:
switch后面的变量需要和case进行匹配,case 值1:成立,执行语句1,
遇见break,switch语句结束;
如果不匹配,继续执行case 值2:成立,执行语句2,break结束
switch语句后面的这个变量名可以是什么样的数据类型呢?
本身能够跟的基本数据类型:byte,short,char,int
Jdk5以后可以是枚举(引用类型) enum
JDK7以后可以跟String类型
switch语句中的注意事项:
1)case语句后面只能是常量
2)在 case语句中,如果匹配成功,就会执行里面的语句,在遇见break之后结束;一定需要写break,如果不写就会造成case穿透,继续执行下面的式子,直到遇见break或执行到句尾才结束。
3)switch中的defalut语句可以在语句的任何位置,不影响语句的执行流程;
正常的格式下,defalut如果在语句末尾,break是可以省略的;
如果在语句中,break必须带上,否则会造成case穿透;
4)switch语句的结束条件:
第一种情况,就是语句break结束; case语句后面的break或者default语句的break
第二种情况,就是语句默认执行到末尾结束!
import java.util.Scanner;
class SwitchDemo2{
public static void main(String[] args){
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请输入一个星期值(1-7):") ;
int weekNum = sc.nextInt() ;
//int b = 3 ;
switch(weekNum){
default:
System.out.println("对不起,您录入的数据不合理") ;
//break ;
case 1:
System.out.println("星期一") ;
break ;
case 2:
System.out.println("星期二") ;
break ;
case 3: //常量
//case b: //变量 //: 需要常量表达式
System.out.println("星期三") ;
break ;
case 4:
System.out.println("星期四") ;
break ;
case 5:
System.out.println("星期五") ;
break ;
case 6:
System.out.println("星期六") ;
break ;
case 7:
System.out.println("星期日") ;
break ;
}
}
}
循环体语句
循环体之for循环
for循环格式
for(初始化语句;条件表达式;控制体语句){
//实际开发中,此处需要去完成一些逻辑判断
循环体语句;
}
执行流程:
1)初始化语句,对变量进行赋值,
2)条件表达式判断结果是否成立,成立,则执行循环体语句,进行控制体语句++或者--
3)继续判断条件表达式是否成立,成立,继续上面这种操作...
循环体之while循环
while循环扩展格式:
初始化语句;
while(条件表达式){
循环体语句;
控制体语句;
}
执行流程:
1)初始化语句进行变量赋值,执行一次;
2)判断条件表达式是否成立,成立,执行循环体语句,依次执行控制体语句;
3)再次回到2)继续操作
...
...
当条件表达式不成立,while循环结束
class WhileDemo{
public static void main(String[] args){
//for循环
for(int x = 1 ; x <=5 ; x++){
System.out.println("天天向上") ;
}
System.out.println("----------------------------------------") ;
/*
初始化语句;
while(条件表达式){
循环体语句;
控制体语句;
}
*/
int i = 1 ;
while(i<=5){
System.out.println("我爱高圆圆") ;
i++ ;
}
}
}
for循环和while循环的区别
1)从用法格式上看,格式不同,while循环的这个格式,不要忽略了控制体语句;
for(初始化语句;条件表达式;控制体语句){
循环体语句;
}
初始化语句;
while(条件表达式){
循环体语句;
控制体语句;
}
2)是否明确循环次数(开发中,优先使用for)
如果需求明确了循环次数,优先使用for循环,工程上的for循环使用最多的!
(最频繁的)
如果不明确循环次数,使用while循环 举例: 猜数字游戏(1-100的数据)
统计才多少次(使用while新年好)
不断录入数据,模拟用户登录
密码和用户名的信息都不一致,错误
否则,登录成功...
3)从内存角度考虑,for循环更优一些,比较节省内存空间
从for循环本身的格式上来说,for循环结束,里面的局部变量(方法定义中的变量)
就被及时的释放空间!
while循环格式,结束之后,依然能够去访问那个变量,(比较消耗内存空间)
所以相对来说whle循环没有for循环好
循环体之do while 循环
do-while循环的格式
初始化语句;
do{
循环体语句;
控制体语句;
}while(条件表达式) ;
初始化语句赋值
判断条件,成立,执行循环体,控制体语句,再次判断....
特点:
和for,while最大的区别就是:即使条件不成立,循环体至少执行一次!
开发中 do-while很少,一般也就是jdk提供的类的源码中会见到!
jdk(sun公司)提供了一个类java.lang.Math (常用类去讲)
(数学运算类,针对三角函数,绝对值,开平方根,向上取整,向下取整等等都可以操作) 不需要导包
有一个功能 public static double random() :获取[0.0,1.0) 之间的随机数
循环体之死循环
两种死循环格式:
for(;;){
循环体语句;
}
while(true){ //推荐这个格式
循环体语句;
}
死循环的格式最终里面完成某个逻辑,当达到某种条件结束循环
会用到一个跳转控制语句 break(中断,结束) ;
不能单独用,它使用在循环语句以及switch语句中;
想要完成一个猜数字游戏:使用循环来操作,不断的键盘录入数据,进行猜
大了,提示大了,
小了,提示小了
如果一致,恭喜猜中了 ,提示 第几次猜中了
键盘录入数据实现
1)产生一个1-100之间的随机数 通过刚才的Math.random() *100+1 --->int
2)不断的键盘录入一个数据,guessNumber (使用死循环while(true)) ,不明确循环次数
3)里面完成逻辑判断
guessNumber比1)产生的随机数大,提示"大了"
guessNumber比1)产生的随机数小,提示"小了"
否则,提示"恭喜您,猜中了"
*/
import java.util.Scanner ;
class WhileTest{
public static void main(String[] args){
//1)产生一个1-100之间的随机数 通过刚才的Math.random() *100+1 --->int
int number = (int)(Math.random()*100+1) ;
//定义统计变量
int count = 0 ;
while(true){//死循环格式
count ++ ;//统计变量++
//2)2)不断的键盘录入一个数据,guessNumer(使用死循环while(true)),不明确循环次数
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
System.out.println("请输入您要猜的数字:") ;
int guessNumber = sc.nextInt() ;
if(guessNumber<=0 || guessNumber>100){
System.out.println("录入的数据不合法") ;
break ;
}else if(guessNumber >number){
//提示"大了"
System.out.println("你要猜的"+guessNumber+"大了") ;
}else if( guessNumber < number){
提示"小了"
System.out.println("你要猜的"+guessNumber+"小了") ;
}else{
System.out.println("恭喜您,第"+count+"次猜中了") ;
break ;//结束中断
}
}
}
}
for 循环嵌套
for循环的嵌套
for循环的循环体语句里面是for循环
for(初始化语句1;条件表达式1;控制体语句1){
for(初始化语句2;条件表达式2;控制体语句2){
循环体语句.....
}
}
跳转控制语句
break
break:结束,中断,不能单独使用!
一般在循环语句(loop),或者是switch语句中用,不能超过这个范围去使用;
for循环嵌套中也可以使用break
public class BreakDemo {
public static void main(String[] args) {
//break ;//超过了switch语句或者循环语句的范围,不能单独用
//switch语句中本来就break语句,
//在 循环语句中,实际业务场景中,当满足某个条件,直接将循环结束了
for(int x = 1 ;x <=10;x++){
// System.out.println(x);//1,2,3,4,5,6,7,8,9,10
if(x == 2){
break ;//结束,中断
}
System.out.println(x);//1
}
continue
continue 结束当前循环,立即进入下一次 循环! (不能单独用,在循环中用)
public class ContinueDemo {
public static void main(String[] args) {
//continue;不能单独用,在循环中用
for(int x = 1 ; x <=10 ; x ++){
if(x == 3){
continue; //结束当前循环,立即进入下一次 循环!
}
System.out.println(x);//1,2,4,5,6,7,8,9,10
}
return
跳转控制语句之return
return:是在Java中跟定义方法相关的,跟有返回值类型的方法有关
它结束有返回值类型的方法去使用的,一般很少单独用(可以用,不建议)
public class ReturnDemo {
public static void main(String[] args) {
System.out.println("程序开始了...");
for(int x = 1 ; x <=10 ; x++){
if(x == 3){
System.out.println("条件成立了");
// break ;
// continue;
//return很少单独用,在有返回值的方法中用的(推荐)
return;//结束方法的
}
System.out.println(x);
}
System.out.println("程序结束了");
}
}
Java中的方法
方法就是通过独立的{}代码块,完成具体的逻辑,给它相应的名字!
(满足标识符的规则:变量和方法名需要满足小驼峰命名法)
Java中定义的方法格式? 有两种定义格式
固定格式:
方式1:有返回值类型的方法定义(在需求中需要根据实际场景需要返回值类型:数据类型)
权限修饰符 static 返回值类型 方法名(参数类型1 参数名称1,参数类型2 参数名称2....){
//完成的方法逻辑操作
return 结果;
}
解释:
权限修饰符 :目前 public 公共,公开的,访问权限足够大
static: 这周面向对象中讲 (必须先上)
返回值类型:现在数据类型(这几天:使用的基本数据类型,以后就是引用类型)
方法名:满足标识符的规则-->方法名需要满足"小驼峰命名法")
参数类型:就是数据类型(这几天:使用的基本数据类型,以后就是引用类型)
参数名称:就是形式参数(变量名)
return:关键字 :这个方法结束,带回结果,谁调用,给谁! (返回结果--->最终 后期交给前端(JavaEE技术))
定义两个数据求和的方法:
心中两个明确
1)明确返回值类型 int
2)明确参数类型以及参数个数
int 2个数据求和
//固定格式
/**
权限修饰符 static 返回值类型 方法名(参数类型1 参数名称1,参数类型2 参数名称2....){
完成的方法逻辑操作
return 结果;
}
定义方法的注意事项:
1)方法和方法是平级关系,不能在一个方法中去定义另一个方法!
2)定义方法的时候,返回值类型需要最终和return语句的结果类型一致,否则报错!
3)有左{ 大括号的地方不能有分号,有分号的地方不能出现"{"
4)定义方法的时候,形式参数类型必须带上,
Java语言强类型语言(语法结构很严谨,不像Javascript,定义函数的时候,不需要写参数类型)
5)调用方法的时候,实际参数要么定义要么键盘录入的,不需要在调用方法里面再去书写数据类型了
Java中定义方法的格式2:
没有具体返回值类型的方法定义
public static 返回值类型 方法名(形式参数类型1 参数名1,.....){
里面直接完成了输出操作或者一些其他逻辑,
没有return关键字
System.out.println("xxxx") ;
}
方法重载
为了标记同一种方法里面可以完成不同参数的使用,为了提高代码的扩展!
java提供overload方法重载
多个方法的方法名可以相同,参数列表不同,与返回值无关!
参数列表不同:可以有下面几种
1) 参数类型不同
2)参数个数不同
3)考虑参数的先后顺序不同
public class FunctionDemo4 {
public static void main(String[] args) {
//调用
//为了方便,直接输出调用
System.out.println(sum(10,20));
// System.out.println(sum2(10,20,30));
// System.out.println(sum3(10,20,30,40));
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,40));
}
//两个数据求和的方法
public static int sum(int a,int b){
return a+b ;
}
//三个数据求和
//public static int sum2(int a,int b ,int c){
public static int sum(int a,int b ,int c){
return a+ b+ +c ;
}
//四个数据求和
//public static int sum3(int a,int b,int c,int d){
public static int sum(int a,int b,int c,int d){
return a+b +c+d ;
}
public static float sum(int a,float b){
return a+b ;
}
public static float sum(float a,int b){
return a+b;
}
public static double sum(double a,double b){
return a+b;
}
public static double SUM(double a,double b){//方法名不同
return a+b;
}
}
数组
动态数组
什么是数组?
数组是一个容器,这个容器能够存储同一种类型的多个元素!
如何定义一个数组?
Java规定有一种固定的格式
数据类型[] 数组名称 ;
数据类型 数组名称[] ;
//举例:int[] arr; 定义一个int类型对数组arr变量
int arr[] ; 定义一个int类型arr数组
创建数组---->对数组进行初始化(创建数组对象)----两种方式
1)动态初始化
2)静态初始化
1)动态初始化:程序员你自己 给定数组长度,系统去默认分配的元素值
数据类型[] 数组名称 = new 数据类型[数组长度];
或者 数据类型 数组名称[] = new 数据类型[数组长度] ;
public class ArrayDemo {
public static void main(String[] args) {
//创建一个数组,动态初始化
int[] arr = new int[3] ;
//解释
//=左边
//int:表示存储 int类型数据
//[]:一维数组(数组默认)
//=右边
//new:Java关键字,表示创建对象,堆内存中开辟空间(new出来的东西在堆中)
//int:表示数组中存储的都是int类型数据
//[]:数组中的长度是3
System.out.println(arr); //打印了 数组名称---就是当前创建数组在堆内存产生的空间地址值
//[I@1540e19d [:一维数组 I:int类型数据 @xxxds :地址值标记
//如何访问数组的元素:数组名称[索引值或者叫角标] ---索引值从0开始算
//访问第一个元素:arr[0]
System.out.println(arr[0]);//0
System.out.println(arr[1]);//0
System.out.println(arr[2]);//0
//重新赋值
arr[0] = 20 ;
arr[1] = 10 ;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
静态数组
指定数组的元素,长度由系统给定
本身的格式
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,元素3...}; 推荐这个
或者
数据类型 数组名称[] = new 数据类型[]{元素1,元素2,元素3...};
简写格式
数据类型[] 数组名称 = {元素1,元素2,元素3...};
或者
数据类型 数组名称[] = {元素1,元素2,元素3...};
举例
int[] arr = new int[]{1,2,3} ;---->int[] arr = {1,2,3} ;
int arr2[] = new int[]{11,22,33} ;--->int arr2[] = {11,22,33} ;
使用静态初始化
不能动静结合!
int[] arr = new int[3]{1,2,3} ; 错误的
public class ArrayDemo4 {
public static void main(String[] args) {
//创建一个数组,静态初始化
//原生格式
// int[] arr = new int[]{11,22,33} ;
//简写格式
int[] arr = {11,22,33} ; //等价于上面的原生格式 :还是在new 创建对象,堆内存中开辟空间
//动静结合(既去用了动态初始化,还同时静态初始化),不行
//int[] arr2 = new int[2]{20,10} ;
System.out.println(arr) ;//地址值
System.out.println(arr[0]);//11
System.out.println(arr[1]);//22
System.out.println(arr[2]);//33
}
}
JVM内存分配
栈内存:
存储局部变量(在方法定义中或者方法声明上),局部变量跟方法有关的;方法进栈,方法调用完毕,里面局部变量随着调用结束
而消失
堆内存:
new出来的东西(引用数据类型)存储在堆中,而且它是随着对象的创建完毕,产生堆内存空间地址值!
方法区:
里面很多的区域:class字节码文件区域---存储字节码文件---jvm需要加载这个类,解析这个类所有的方法以及变量(---这个过
程"反射技术")
static区域:----静态区域--存储跟static相关的一些方法以及变量等等
constant pooll:常量池 里面存储常量相关的
本地方法区(了解): 和系统相关的----->创建系统资源完成系统相关的操作
寄存器(了解): 和系统cpu都有关系:电脑的核数(16核/8核的)--核数越大,高并发场景下,运行效率越高;
冒泡排序
/*
冒泡排序思想:
两两比较,如果前面的元素比后面元素大,将前面的元素往后放(较大的值往后走),第一次比较完毕,最大值就出现在最大索
引处;依次这样比较,就可以得到一个排好序的数组!
规律:
两两比较,如果前面的元素比后面元素大,将前面的元素往后放;
第一次比较:有0个不比,都得比
第二次比较:有1个不比
...
每次比较一次,下一次就减少一次比较的次数
最终比较的次数:数组长度-1次
*/
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[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp ;
}
}
}
}
基本数据类型和引用数据(数组,类,接口)他们作为方法的形式参数的各自特点!
形式参数如果是基本数据类型,形式参数的改变不影响实际参数!
后面特殊的引用数据类型:String,作为形式参数和基本类型数效果一致!
局部变量的生命周期:(方法定义中,或者方法声明上):局部变量随着方法调用而存在,随着方法调用结束而消失
public class ArrayTest {
public static void main(String[] args) {
//下面代码,写成结果
int a = 10 ;
int b = 20 ;
System.out.println("a:"+a) ;
System.out.println("b:"+b) ;
change(a,b) ;
System.out.println("a:"+a) ;//10
System.out.println("b:"+b) ;//20
引用类型作为形式参数,形式参数的改变是直接影响实际参数的,
因为引用数据类型(数组,类,接口),是一种空间地址值进行传递,而基本数据类型只是数据值进行传递(随着方法调用存在,调用结束而消失)
而引用类型---需要new--->需要在堆内存中开辟空间,对象使用完了,不会立即被回收,需要等待gc垃圾回收器空闲时刻自己回收!
对象一旦被创建,永远指向那个地址值,除非重新new对象
public class ArrayTest2 {
public static void main(String[] args) {
//创建一个数组,静态初始化
int[] arr = {1,2,3,4,5} ;
System.out.println(arr[1]);//2
change(arr) ;//----{1,4,3,8,5}
System.out.println(arr[1]); //4
}
public static void change(int[] arr){//引用数据类型数组作为参数传递---空间地址值
//遍历了数组
for(int x= 0 ; x < arr.length ;x++){
//获取到元素
if(arr[x] %2==0){
arr[x]*=2 ;
}
}
}
}
局部变量和成员变量有什么区别?
1)书写位置的区别
局部变量:在方法定义中或者方法声明上的变量
成员变量:类中方法外!
实际开发中:根据具体的情况具体使用,范围越小越好,因为范围小,使用完,释放内存了!
2)内存位置不同
局部变量:在栈内存中---跟方法有关(方法进栈)
成员变量:在堆内存中---跟对象有关 (类名 对象名 = new 类名();)
3)生命周期不同:
局部变量:随着方法调用而存在,随着方法调用结束而消失
成员变量:随着对象的创建而存在,随着对象的创建完毕后,使用完毕(访问成员变量/访问成员方法)之后等待
垃圾回收器空闲时候回收而消失!(不会立即释放)
4)初始化值不同
局部变量:在使用之前必须初始化,否则报错
成员变量:跟对象有关系,存在系统默认初始化,然后可以显示初始化 对象名.成员变量名=赋值;
什么是类(Java编程语言中)–>就是现实世界中的真实存在的事物
类:是Java语言中最基本的单元;能够描述现实世界事物的一组事物的属性和行为的集合!
类和现实世界事物是一一对应的关系;
类的概念 clss Student{}
--- 成员变量---类中方法外, name,age,gender
--- 成员方法--- study()
如何将现实生活中的真实存在的事物---->我们的代码(以Java编程方式写出来进行测试)
事物 学生事物
--- 属性 姓名,年龄,性别
--- 行为 学习
对象是什么---------->体现出来的现实生活着具体的事物
java代码中体现一个具体的事物(使用对象来描述)
类名 对象名= new 类名() ; 创建一个对象(描述现实生活中具体事物)
面向对象的思想特点
面向对象的思想特点:
1)更符合现实生活中的思想行为习惯
2)让复杂的事情简单化
3)角色发生了改变:从执行者(面向过程)--->变成指挥者(面向对象)
面向对象的设计理念和三大特征
面向对象的设计理念:
不断的创建对象,使用对象,指挥对象做事情!
面向对象的三大特征:封装,继承,多态(面向对象重点)
什么是对象
对象:描述现实世界的具体事物!(具体事物的具体的属性和行为)
在代码中体现出来具体事物----->需要记住Java中的创建类对象的格式
类名 对象名 = new 类名() ;
对象名.成员变量名 = 值 (根据成员变量的类型赋值); 访问成员变量 赋值
对象名.方法名(); 访问我们自己的定义的成员方法,去使用它,展示数据或者实现具体业务需求
形式参数是基本类型和引用类型,实际参数传递问题! (重点要就引用类型)
形式参数是基本类型,调用该方法,实际参数传递对应类型的数据值即可(简单,数据值传递)
形式参数是引用类型(如果是类),调用这个方法,实际参数传递需要传递当前类的具体对象 (创建类对象)
匿名对象
匿名对象格式:
new 类名();
特点:
1)可以作为"参数传递"
2)实际用的过程,匿名对象不要多次,一般使用一次即可,使用完毕立即被回收!
public class NoNameDemo {
public static void main(String[] args) {
//使用有名字的对象访问:
//访问PersonDemo类中 function()方法
PersonDemo pd = new PersonDemo() ; //创建PersonDemo类对象
//创建Person类对象
Person p = new Person() ;
pd.function(p);//创建Person类对象进行实际参数传递
System.out.println("------------------------------------------------------");
//匿名对象的格式 :new 类名(); --可以作为参数传递
//访问PersonDemo类中 function()方法
PersonDemo pd2 = new PersonDemo() ;
pd2.function(new Person());
System.out.println("------------------------------------------------------");
//链式编程 (实际开发中:不推荐这种,自己去使用可以用这种格式)
//访问PersonDemo类中 function()方法
new PersonDemo().function(new Person());
封装
就是保证成员属性的数据安全性,让外界类不能直接操作,只能在本来中去访问加入private(属性私有化,对外隐藏了)
对外必须提供公共的成员方法setXXX()/getXXX()来赋值,和获取值!
private :私有的 ,修饰的成员变量或者成员方法只能本类中访问 (为了保证数据安全)
public class Student {
//属性私有化
private String name ;//姓名
private int age ; //年龄
private String gender ; //性别
//对外提供公共的成员方法
//赋值的方法setXXX() ---->传入形式参数
//给成员name赋值
//public void setName(String n){ // 高 n
/*
name = n ; //高
}*/
//给成员name赋值,优化
public void setName(String name){ //形式参数也是 name
//name = name ; //提供this 区分成员变量和局部变量
this.name = name ;
}
//所有的getXXX()--->return 隐藏了this关键字(可以省略不写)
//获取成员变量name的值--考虑返回值类型
public String getName(){
return name ; //高
}
//给age赋值
/* public void setAge(int a){ //44 a
age = a ; //44
}*/
//优化
public void setAge(int age) { //44
this.age = age;
}
//获取age的值
public int getAge(){
return age ; //44
}
public class StudentTest {
public static void main(String[] args) {
//创建学生对象
//类名 对象 = new 类名() ;
Student s = new Student() ;
//成员变量私有化了:不能直接访问
//s.name= "高" ;
// System.out.println("姓名是:"+s.name);
//通过公共的setXXX(xxx)赋值
s.setName("高") ;
s.setAge(44) ;
s.setGender("女") ;
//通过getXXX()方法获取值
System.out.println("这个学生的姓名是"+s.getName()+",年龄是:"+s.getAge()+",性别是:"+s.getGender());
s.study("JavaSE之面向对象");
}
}
this关键字
this的含义: 代表当前类对象的地址值引用
加入this---->标准类的写法 (描述学生事物/描述手机事物)
this 用于区分当前类的属性和局部变量