目录
面试题
if…else…和三元运算符的区别?
共同点:都是针对两种情况进行判断,都有表达式;
不同点:
*if...else...流程控制语句,范围很大,不仅仅可以操作数据值,还可以操作输出语句去完成逻辑判断;而三元运算符仅仅是运算符,操作两个具体的数据值;
*三元运算符能实现的一定能够使用if...else...流程语句
*if....else....流程语句实现的,不一定能够使用三元!(流程控制语句操作 System.out.println())
switch语句后面的变量名可以是什么样的数据类型呢?
本身能够跟的基本数据类型:byte,short,char,int
Jdk5以后可以是枚举(引用类型) enum
JDK7以后可以跟String类型
for和while循环有什么区别?
1)从用法格式上看,格式不同,while循环的这个格式,不要忽略了控制体语句;
for(初始化语句;条件表达式;控制体语句){
循环体语句;
}
初始化语句;
while(条件表达式){
循环体语句;
控制体语句;
}
2)是否明确循环次数(开发中,优先使用for)
如果需求明确了循环次数,优先使用for循环,工程上的for循环使用最多的!
(最频繁的)
如果不明确循环次数,使用while循环
* 举例: 猜数字游戏(1-100的数据)
统计才多少次(使用while新年好)
不断录入数据,模拟用户登录
密码和用户名的信息都不一致,错误
否则,登录成功...
3)从内存角度考虑,for循环更优一些,比较节省内存空间
从for循环本身的格式上来说,for循环结束,里面的局部变量(方法定义中的变量)就被及时的释放空间!
while循环格式,结束之后,依然能够去访问那个变量,(比较消耗内存空间)所以相对来说whle循环没有for循环好
形式参数是基本数据类型和引用类型(重点)的区别
形式参数如果是基本类型,形式参数改变不影响实际参数(包括特殊的应用java.lang.String)
形式参数如果是引用数据类型,形式参数的改变直接影响实际参数的
局部变量和成员变量有什么区别?
局部变量和成员变量有什么区别?
- 1)书写位置的区别
- 局部变量:在方法定义中或者方法声明上的变量
- 成员变量:类中方法外!
- 实际开发中:根据具体的情况具体使用,范围越小越好,因为范围小,使用完,释放内存了!
- 2)内存位置不同
- 局部变量:在栈内存中—跟方法有关(方法进栈)
- 成员变量:在堆内存中—跟对象有关 (类名 对象名 = new 类名()😉
- 3)生命周期不同:
- 局部变量:随着方法调用而存在,随着方法调用结束而消失
- 成员变量:随着对象的创建而存在,随着对象的创建完毕后,使用完毕(访问成员变量/访问成员方法)之后等待
- 垃圾回收器空闲时候回收而消失!(不会立即释放)
- 4)初始化值不同
- 局部变量:在使用之前必须初始化,否则报错
- 成员变量:跟对象有关系,存在系统默认初始化,然后可以显示初始化 对象名.成员变量名=赋值;
if…else…嵌套
if....else....一种嵌套 (不推荐,知道可以实现解决一些问题)
if(表达式1){
if(表达式2){
语句1;
}else{
语句2;
}
}else{
if(表达式3){
语句3;
}else{
语句4;
}
}
流程控制语句之switch
//格式:
switch(变量名){
case 值1:
语句1;
break ;
case 值2;
语句2;
break ;
....
....
....
default:
语句n;
break ;
}
执行流程:
switch后面的变量需要和case进行匹配,case 值1:成立,执行语句1,
遇见break,switch语句结束;
如果不匹配,继续执行case 值2:成立,执行语句2,break结束
switc语句中的注意事项:
1)case语句的后面只能是常量(在Java语言中:强类型语言:语法结构很严谨),而前端javascript里面的switch语句的case可以是常量,变量;
2)在case语句里面,如果一旦匹配成功,一定书写break;否则会造成case穿透,case匹配成功了,就会执行里面的语句,遇见break语句结束; (这个现象 “灵活运用”)
3)switch中的default语句可以在语句中的任何位置,不影响语句的执行流程
正常的格式,在语句末尾,break可以是省略的;
如果在语句中,break带上,否则case穿透了 (考点)
4)switch语句的结束条件:
第一种情况,就是语句break结束; case语句后面的break或者default语句的break
第二种情况,就是语句默认执行到末尾结束!
循环结构语句
for 语句
循环结构语句:当需求中有这种循环的思想,就需要使用循环语句去实现
for循环格式
for(初始化语句;条件表达式;控制体语句){
//实际开发中,此处需要去完成一些逻辑判断
循环体语句;
}
执行流程:
1)初始化语句,对变量进行赋值,
2)条件表达式判断结果是否成立,成立,则执行循环体语句,进行控制体语句++或者--
3)继续判断条件表达式是否成立,成立,继续上面这种操作...
...
...
如果控制体语句造成了条件表达式不成立,语句结束!
求和思想
统计思想
for-while的区别
for和while死循环格式(使用while(true)居多)
跳转语句
引入方法
/*需求:
求5的阶乘
n! = n*(n-1)*(n-2)...4 * 3 * 2 * 1
求阶乘思想
1)定义最终结果变量
int jc = 1 ;
2)循环:5的阶乘 ---- 明确了范围 int x= 1 ; x <=5 ;x++
jc *= x; //x = 1 ,1<=5 , x++ , 2 <=5
//jc = 1 * 1 =1 , jc=1*2
3)输出结果变量即可
*/
class ForDemo2{
public static void main(String[] args){
//求5的阶乘
//定义结果变量
int jc = 1 ;
for(int x = 2 ; x <= 5 ; x++){ //初始化语句 从2开始
//循环体
jc *= x ;//1*1 永远是1
}
System.out.println("5的阶乘是:"+jc) ;
}
}
水仙花数
/*需求:在控制台输出所有的水仙花数
水仙花:水仙花是一个三位数,特点就是每个位上的立方之和的结果就是当前数据本身
153=1*1*1 + 5*5*5 + 3*3*3
分析:
1)明确范围三位数,使用for 初始化语句:变量x
2)确定了范围,如何获取每个位的数据呢,个位,百位,十位?(关键)
2.1)定义三个变量 int ge,int shi ,int bai
个位数据 = 就使用x%10 ;
十位上的数据 = x /10 %10 ;
百位上的数据 = x/10 /10 %10;
2.2)完成逻辑判断
满足条件:如果x的值 == (ge*ge*ge+shi*shi*shi+bai*bai* bai)
2.3)输出这个x值,即可
*/
class ForDemo3{
public static void main(String[] args){
System.out.println("水仙花数是:") ;
//在控制台输出所有的水仙花数
//1)明确范围三位数,使用for 初始化语句:变量x
for(int x = 100; x <1000; x++){
//2)定义三个变量:分别代表个位数据,十位数据,百位上的数据
int ge = x % 10 ; //153 % 10 = 3
//去掉了低位,再去对10求余 //153 /10 % 10 = 5
int shi = x / 10 % 10 ;
int bai = x/10/10%10 ; //153/100 %10 = 1
//完成逻辑判断
//满足条件:如果x的值 == (ge*ge*ge+shi*shi*shi+bai*bai* bai)
if(x==(ge*ge*ge+shi*shi*shi+bai*bai* bai)){
//输出x
System.out.println(x) ;
}
}
}
}
统计思想
/*
统计思想:
统计所有的水仙花有多少个?
1)定义统计变量
2)分析题意,明确范围,for循环
3)满足条件,则统计变量++
4)输出统计变量
*/
class ForTest{
public static void main(String[] args){
//1)定义统计变量
int count = 0 ;
//2)统计所有水仙花----水仙花 三位数,明确范围 for循环
for(int x= 100 ; x<=999; x++){
//2.1)确定每个位数据
int ge = x %10 ;
int shi = x/10%10;
int bai = x/10/10%10 ;
//2.2)满足条件,统计变量++
if(x==(ge*ge*ge+shi*shi*shi+bai*bai*bai)){
count ++ ;//统计变量++
System.out.println("第"+count+"个,水仙花数是:"+x) ;
}
}
System.out.println("所有的水仙花共有"+count+"个") ;
}
}
for循环嵌套
for(初始化语句1;条件表达式1;控制体语句1){
for(初始化语句2;条件表达式2;控制体语句2){
循环体语句.....
}
}
示例:
需求:
输出四行5列的*形
*****
*****
*****
*****
*/
class ForForDemo{
public static void main(String[] args){
//原始的做法:
System.out.println("*****") ;
System.out.println("*****") ;
System.out.println("*****") ;
System.out.println("*****") ;
//不好,上面的代码,冗余度太大(重复度太大)
System.out.println("---------------------------------------") ;
//循环思想改进
for(int x = 0 ; x < 4 ; x ++){//0,1,2,3
System.out.println("*****") ;
}
System.out.println("---------------------------------------") ;
//上面虽然可以,使用for循环,但是*,单独去输出 冗余度在低一些
//一行5个*,我可以将一行的每一个*都使用for循环操作
//每一个*在同一行上,将输出语句System.out.print() ,在同一行上打印
//第一行的5个*
for(int x = 0 ;x < 5 ;x++){ //0,1,2,3,4
System.out.print("*") ;
}
//换行
System.out.println() ;
System.out.println("--------------第二行----------------") ;
//第二行 还是5个*
for(int x = 0 ;x < 5 ;x++){ //0,1,2,3,4
System.out.print("*") ;
}
//换行
System.out.println() ;
System.out.println("--------------第三行----------------") ;
//第三行 还是5个*
for(int x = 0 ;x < 5 ;x++){ //0,1,2,3,4
System.out.print("*") ;
}
//换行
System.out.println() ;
System.out.println("--------------第四行----------------") ;
//第四行 还是5个*
for(int x = 0 ;x < 5 ;x++){ //0,1,2,3,4
System.out.print("*") ;
}
//换行
System.out.println() ;
System.out.println("----------------将上面代码最终优化为:------------------------") ;
//上面代码也能够实现,冗余度还是存在,为了更好的去书写
//使用for循环嵌套,上面的代码循环四次
for(int x = 0 ; x < 4 ; x ++){//行数,四行,x= 0 ,1,2,3
for(int y = 0 ;y < 5 ;y++){ //列数,5列 y=0,1,2,3,4
System.out.print("*") ;
}
//换行
System.out.println() ;
}
}
}
打印九九乘法表
class ForForTest{
public static void main(String[] args){
//6行6列的*形
for(int x= 0 ; x <6 ;x++){//行数
for(int y = 0 ; y < 6 ;y++){
System.out.print("*") ;
}
System.out.println() ;
}
System.out.println("-----------------------------------------") ;
//现在列数随着行的变化而变化
//6行6列,列数有变化
for(int x= 0 ; x <6 ;x++){//行数
for(int y = 0 ; y <=x ;y++){//列数
System.out.print("*") ;
}
System.out.println() ;
}
System.out.println("-----------------------------------------") ;
//99乘法表:跟我们的这个上面的格式一样
//为了保证有数据 数据从1开始
for(int x = 1 ; x <=9 ; x ++){//行数
for(int y = 1 ; y <=x ; y ++){//列数,在变化
//循环体语句
//转义字符: "\t" 制表符 类似tab键的效果
System.out.print(x +"*"+y+"="+(y*x)+"\t") ;
}
System.out.println() ;
}
}
}
for循环语句嵌套的应用——百钱买百鸡
public static void main(String[] args) {
//定义公鸡为x,母鸡为y,小鸡为z
int x, y, z;
for (x = 0; x <= 20; x++) {
for (y = 0; y <= 33; y++) {
z = 100 - x - y;
if ((5 * x + 3 * y + z / 3) == 100 && x + y + z == 100 && z % 3 == 0) {
System.out.println("公鸡" + x + "母鸡" + y + "小鸡" + z);
}
}
}
}
while语句
while循环扩展格式:
初始化语句;
while(条件表达式){
循环体语句;
控制体语句;
}
执行流程:
1)初始化语句进行变量赋值,执行一次;
2)判断条件表达式是否成立,成立,执行循环体语句,依次执行控制体语句;
3)再次回到2)继续操作
...
...
当条件表达式不成立,while循环结束
/*
使用while循环来完成
1)1-100之间的和
2)1-100之间的偶数和
3)输出所有的水仙花数
4)统计所有水仙花的个数
*/
class WhileTest{
public static void main(String[] args){
//1-100之间的和
int i = 1 ;
//定义结果变量
int sum = 0 ;
while(i<=100){
sum += i ;
i++ ;
}
System.out.println("1-100之间的和是:"+sum);
System.out.println("---------------------------") ;
//1-100之间的偶数和
int x = 1;
//结果变量
int sum2 = 0 ;
while(x<=100){
//满足偶数
if(x % 2 ==0){
sum2 +=x ;
}
x++;
}
System.out.println("1-100之间偶数和是:"+sum2);
System.out.println("---------------------------") ;
//输出所有的水仙花数
//水仙花三位数
System.out.println("水仙花数是:") ;
int j = 100 ;
while(j<=999){
//定义三个变量,ge,shi,bai
int ge = j % 10 ;
int shi = j /10 % 10;
int bai = j /10/10 %10 ;
//满足条件
if(j==(ge*ge*ge+shi*shi*shi+bai*bai*bai)){
System.out.println(j) ;
}
j++;
}
System.out.println("---------------------------") ;
//统计水仙花多少个?
//定义统计变量
int count = 0 ;
int m = 100 ;
while(m<=999){
//定义三个变量,ge,shi,bai
int ge = m % 10 ;
int shi = m /10 % 10;
int bai = m /10/10 %10 ;
//满足条件
if(m==(ge*ge*ge+shi*shi*shi+bai*bai*bai)){
//统计变量++
count ++ ;
System.out.println("第"+count+"个,水仙花数是"+m) ;
}
m++ ;
}
System.out.println("水仙花共有"+count+"个") ;
}
dowhile
初始化语句;
do{
循环体语句;
控制体语句;
}while(条件表达式) ;
初始化语句赋值
判断条件,成立,执行循环体,控制体语句,再次判断....
特点:和for,while最大的区别就是:即使条件不成立,循环体至少执行一次!
开发中 do-while很少,一般也就是jdk提供的类的源码中会见到!
两种死循环
for死循环格式
for(;;){
循环体语句;
}
while死循环
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 ;//结束中断
}
}
}
}
跳转控制语句 break,continue,return
break语句
break:结束,中断,不能单独使用!
一般在循环语句(loop),或者是switch语句中用,不能超过这个范围去使用;
for循环嵌套中也可以使用break
break 标签名称; 在多层循环嵌套的时候,标签名称就是给循环语句前面加上的标签名字(以前的早期用法)
xx:for(初始化语句;条件表达式;控制体语句){
}
continue语句
跳转控制语句
continue 结束当前循环,立即进入下一次 循环! (不能单独用,在循环中用)
return跳转控制语句
return:是在Java中跟定义方法相关的,跟有返回值类型的方法有关
它结束有返回值类型的方法去使用的,一般很少单独用(可以用,不建议)
return实际开发中,和方法息息相关(下午分解)
Java中的方法
解释
权限修饰符 :目前 public 公共,公开的,访问权限足够大
static: 这周面向对象中讲 (必须先上)
返回值类型:现在数据类型(这几天:使用的基本数据类型,以后就是引用类型)
方法名:满足标识符的规则-->方法名需要满足"小驼峰命名法")
参数类型:就是数据类型(这几天:使用的基本数据类型,以后就是引用类型)
参数名称:就是形式参数(变量名)
return:关键字 :这个方法结束,带回结果,谁调用,给谁! (返回结果--->最终 后期交给前端(JavaEE技术))
方法就是通过独立的{}代码块,完成具体的逻辑,给它相应的名字!(满足标识符的规则:变量和方法名需要满足小驼峰命名法)
固定格式
方式1:有返回值类型的方法定义(在需求中需要根据实际场景需要返回值类型:数据类型)
权限修饰符 static 返回值类型 方法名(参数类型1 参数名称1,参数类型2 参数名称2....){
//完成的方法逻辑操作
return 结果;
}
方式二:没有具体返回值类型的方法定义
public static 返回值类型 方法名(形式参数类型1 参数名1,.....){
里面直接完成了输出操作或者一些其他逻辑,
没有return关键字
System.out.println("xxxx") ;
}
在一些具体的业务场景中,像数组排序,99乘法表,猜数字游戏(提示"大了,小了,还是猜中了..."),没有具体的返回结果但是还要遵循方法定义格式,所以Java提供了关键字void 充当这个返回值类型,只是没有具体返回结果的一种格式而已!没有具体返回结果的方法的定义格式 (回想:我们的main这样写的)
public static void 方法名(形式参数类型1 参数名1,.....){
里面直接完成了输出操作或者一些其他逻辑,
没有return关键字
System.out.println("xxxx") ;
}
方式1-有具体返回值的方法的调用
- 1)单独调用
- 2)输出调用
- 3)赋值调用
方式2—调用:
- 单独调用(只能用这个)
- 输出调用
- 赋值调用
定义方法的注意事项
定义方法的注意事项:
- 方法和方法是平级关系,不能在一个方法中去定义另一个方法!
- 定义方法的时候,返回值类型需要最终和return语句的结果类型一致,否则报错!
- 有左{ 大括号的地方不能有分号,有分号的地方不能出现"{"
- 定义方法的时候,形式参数类型必须带上,Java语言强类型语言(语法结构很严谨,不像Javascript,定义函数的时候,不需要写参数类型)
- 调用方法的时候,实际参数要么定义要么键盘录入的,不需要在调用方法里面再去书写数据类型了
方法重载
Java中有一个规定:标识符里面规则: 给方法起名,见名知意!
为了标记同一种方法里面可以完成不同参数的使用,为了提高代码的扩展!
java提供overload方法重载:多个方法的方法名可以相同,参数列表不同,与返回值无关!
参数列表不同:可以有下面几种
参数类型不同
参数个数不同
考虑参数的先后顺序不同
猜大小小游戏(用方法来写)
ublic static void main(String[] args) {
//main方法中 代码,越少越好
//调用我们写的方法
playGuessNumberGame();
}
/**
* 定义一个方法,里面是猜数字游戏
* 两个明确
* 明确返回值类型:没有具体返回结果,直接输出
* 明确参数类型以及参数个数
* 空参
*/
public static void playGuessNumberGame(){
//产生随机数 1-100之间随机数
int number = (int) (Math.random()*100+1) ;
//定义统计变量
int count = 0 ;
//不断的键盘录入数据
while(true){
count ++ ;
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
System.out.println("请您要输入要猜的数字(1-100):");
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;
}
}
}
Jvm内存分配:栈,堆,方法区,本地方法区(和系统相关),寄存器(和系统相关)
- 栈内存:存储局部变量(在方法定义中或者方法声明上),局部变量跟方法有关的;方法进栈,方法调用完毕,里面局部变量随着调用结束而消失
- 堆内存:new出来的东西(引用数据类型)存储在堆中,而且它是随着对象的创建完毕,产生堆内存空间地址值!
- 方法区:里面很多的区域:class字节码文件区域—存储字节码文件—jvm需要加载这个类,解析这个类所有的方法以及变量(—这个过程"反射技术")
- static区域:----静态区域–存储跟static相关的一些方法以及变量等等
- constant pooll:常量池 里面存储常量相关的
- 本地方法区(了解): 和系统相关的----->创建系统资源完成系统相关的操作
- 寄存器(了解): 和系统cpu都有关系:电脑的核数(16核/8核的)–核数越大,高并发场景下,运行效率越高;
数组
什么是数组
数组是一个容器,这个容器能够存储同一种类型的多个元素!
如何定义一个数组?
Java规定有一种固定的格式
- 数据类型[] 数组名称 ;
- 数据类型 数组名称[] ;
创建对象的内存图解
创建一个对象
创建两个对象
创建多个对象
创建数组的两种方式
- 动态初始化:程序员你自己 给定数组长度,系统去默认分配的元素值
- 数据类型[] 数组名称 = new 数据类型[数组长度];
- 数据类型 数组名称[] = new 数据类型[数组长度] ;
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…};
ps:使用静态初始化,不能动静结合!
创建数组_静态初始化的过程
数组的应用
静态初始化,将数组的遍历
public static void main(String[] args) {
//创建一个数组,静态初始化
int[] arr = {11,22,33,44,55} ;
//原始的做法:
//通过数组名称[索引值]访问
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]); //ctrl+d:复制行
System.out.println(arr[3]) ;
System.out.println(arr[4]) ;
System.out.println("---------------------------------");
//改进:上面代码冗余度很高,arr[索引值在变化]---循环改进:for
for(int x = 0 ; x < 5 ; x ++){ //0,1,2,3,4 索引值
System.out.println(arr[x]) ;
}
System.out.println("---------------------------------");
//上面的这个5:数出来的,不太好
//假设有一个数组:
//int[] arr2 = {10,20,11,22,66,5,3,12,15,99,45,32,12,44} ;
//当数组的元素比较多:---数组提供了属性:length属性 :获取数组长度的
//数组名称.length---获取数组长度 ---数组的最大索引值 = 数组长度-1
//System.out.println(arr.length);
// System.out.println(arr2.length);
for(int x = 0 ; x < arr.length ; x ++){ //0,1,2,3,4 索引值
System.out.println(arr[x]) ;
}
System.out.println("--------------------------------------------------");
//继续优化----我们昨天学习了方法----->将数组遍历的操作----使用方法改进!
//单独调用
printArray(arr);
System.out.println("---------------------最终版代码---------------------------");
printArray2(arr);
}
/*
* 定义一个方法:方法最终输出数组的格式:
* [元素1, 元素2, 元素3, 元素4, 元素5, ....]
* */
public static void printArray2(int[] arr){ //类型是一个数组类型
//[元素1, 元素2, 元素3, 元素4, 元素5, ...元素n]
//1在同一个行上-不换行输出"["
System.out.print("[");
//2)遍历数组,获取到每一个元素
for(int x = 0 ; x < arr.length ;x++){
//完成逻辑判断
//如果角标值 == 数组长度-1 :
// 说明当前已经取到最大角标值,数组的元素已经到达末尾,应该最后一个元素以及右"]"输出,换行
if(x== arr.length-1){
System.out.println(arr[x]+"]");
}else{
//说明没有取到最大角标值,中间对应的元素应该 元素内容 + ", " ,在同一行上
System.out.print(arr[x]+", ");
}
}
}
/*
* 定义一个方法:遍历数组元素---将元素的内容输出控制台
* 两个明确
* 1)明确返回值类型:没有具体返回值 void
* 2)明确参数类型以及参数个数:
* 参数类型---int类型数组,1个参数
* */
public static void printArray(int[] arr){//参数是数组类型 arr是形式参数
for(int x = 0 ; x < arr.length ; x ++){ //0,1,2,3,4 索引值
System.out.println(arr[x]) ;
}
}
最值问题
public static void main(String[] args) {
//已知一个数组,静态初始化
int[] arr = {24,67,98,12,56} ;
//定义一个参照物,将arr[0]看成是最大值
int max = arr[0] ;
//从角标1开始遍历后的元素
for(int x = 1 ; x < arr.length ;x ++){
//一一获取到元素了
//进行判断
//如果后面的元素比参照物还大max还打,那么将后面的元素赋值 给max
if(arr[x] >max){//arr[1] > max arr[2] > max arr[3] > max不成立
max = arr[x] ;
}
}
System.out.println("数组中的最大值是:"+max);
System.out.println("----------------------------------------------") ;
//调用方法
int max2 = getArrayMax(arr);
System.out.println("使用方法改进获取的数组最大值是:"+max2);
}
/**
* 定义一个方法:获取数组中的最大值
* 两个明确
* 1)明确返回值类型 :int类型
* 2)明确参数类型以及参数个数
* int[] 数组,1个参数
*/
public static int getArrayMax(int[] arr){//需要传递数组对象---在main中创建一个数组,静态初花了
//定义参照物
int max = arr[0] ;
//从角标1开始遍历后面的元素
for (int i = 0; i < arr.length; i++) {
//如果后面元素比参照物大,将后面元素赋值给max
if(arr[i]>max){
max = arr[i] ;
}
}
return max ;
}
假设思想
数组的基本查找
特点:数组无序或者有序都可以,从头查到尾部,如果查不到,返回负数(找不到,-1)
后面将高级查找 (二分搜索法,也称为"折半查找":前提条件,数组必须有序!)
jdk工具类—Arrays—>binarySearch(int[] arr,int target)—>获取元素第一次出现索引值
public static void main(String[] args) {
//已知一个数组:静态初始化
int[] arr = {24,87,15,69,45} ;
//查询87这个元素在数组第一次出现的索引值
//使用方法来完成
int index = getIndex(arr,87) ;
System.out.println("87这个元素第一次出现的索引值是:"+index) ;
int index2 = getIndex(arr,99) ;
System.out.println("99这个元素第一次出现的索引值是:"+index2) ;
System.out.println("------------------------------------------------------------");
//调用方法
int index3 = getIndex2(arr,120) ;
System.out.println(index3);
int index4 = getIndex2(arr,45) ;
System.out.println(index4);
}
//方式2实现 假设思想
/**
* 获取数组的元素第一次出现索引值
* @param array 要查找指定数组
* @param target 要查找的指定元素
* @return 返回的内容就是该元素的索引值
*/
public static int getIndex2(int[] array,int target){
//假设找不到就是-1
int index = -1 ; //索引值-1
//遍历数组
for(int i = 0 ; i < array.length;i++){
//一一获取数组元素,如果target == array[i],将index的值修改了,将i值赋值给index ,循环结束
if(target== array[i]){
//找到了这个元素
//修改index值
index = i ;
break ;
}
}
return index;
}
//方式1
//定义一个方法:获取数组的中的元素索引值
/**
* 两个明确
* 明确返回值类型: int
* 明确参数类型以及参数个数:
* 2个参数需要
* 1一个数组
* 1一个是找的元素
*/
public static int getIndex(int[] array,int target){//array:指定的数组中查询,target:找的元素
//1)直接遍历数组
for(int i = 0 ; i < array.length; i ++){
//2)一一获取到数组元素,如果这个target就是跟array[i]一致,说明target就是我们要找的元素
if(target == array[i]){
//返回角标值即可;
return i ;
}
}
//如果找了一圈,for结束了,还找不到,返回-1
return -1 ;
}
数组的高级排序——冒泡排序
两两比较,将较大的值往后放,第一次比较完毕,最大值就出现在最大索引处
依次这样比较,可以得到一个排好序的数组;
规律:
1)两两比较,较大的值往后放
2)第一次有0个不比,
第二次有1个不比
第三次有2个不比
…
比较的次数:数组长度-1次
public static void main(String[] args) {
//已知数组,静态初始化
int[] arr = {24,69,87,56,13} ;
System.out.println("排序前原始数组是:");
//调用数组的遍历方法---将数组 [元素1, 元素2, 元素3,.... 元素n] 输出,展示
printArray(arr);
System.out.println("---------------------------------------------") ;
//第一次比较:
//arr.length-1:为了防止角标越界
//arr.length-1-0:第一次比较,有0个不比(都得比较)
/*
for(int x=0 ; x < arr.length-1-0 ; x ++){
//核心代码
//如果前的元素比后面的元素大,将前面的元素( 大的值)往后放
if(arr[x]> arr[x+1]){//arr[0] arr[0+1]
//中间变量的方式
int temp = arr[x] ;
arr[x] = arr[x+1] ;
arr[x+1] = temp ;
}
}
System.out.println("第一次比较完毕后: ");
//调用遍历的方法:展示数组元素
printArray(arr);
System.out.println("-----------------------------------------------") ;
//第二次比较
//arr.length-1:防止角标越界
//arr.length-1-1: 第二次比较有1个不比
for(int x = 0 ; x < arr.length-1-1;x++){
if(arr[x] > arr[x+1]){
int temp = arr[x] ;
arr[x] = arr[x+1] ;
arr[x+1] = temp;
}
}
System.out.println("第二次比较完毕后:");
printArray(arr);
System.out.println("------------------------------------");
//第三次比较
//arr.length-1:防止角标越界
//arr.length-1-2:第三次比较有2个不比
for(int x = 0 ; x < arr.length-1-2;x++){
if(arr[x] > arr[x+1]){
int temp = arr[x] ;
arr[x] = arr[x+1] ;
arr[x+1] = temp;
}
}
System.out.println("第三次比较完毕之后:");
printArray(arr);
System.out.println("------------------------------------");
//第四次比较
//arr.length-1:防止角标越界
//arr.length-1-3:第四次比较有3个不比
for(int x = 0 ; x < arr.length-1-3;x++){
if(arr[x] > arr[x+1]){
int temp = arr[x] ;
arr[x] = arr[x+1] ;
arr[x+1] = temp;
}
}
System.out.println("第四次比较完毕之后:");
printArray(arr);
*/
//将上面的重复性代码进行优化:冗余度太大
//循环了四次
/*for(int x = 0 ; x < 4;x++){//x=0,1,2,3 4是数的 (控制次数)
//x=0,0<4,
for(int y = 0 ;y < arr.length-1-x;y++){
//arr[0] ; y< arr.length-1-0 :第一次有0 个不比
if(arr[y] > arr[y+1]){ //arr[0] arr[1]
int temp = arr[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp;
}
}
}
System.out.println("排序之后:");
//调用遍历
printArray(arr);*/
System.out.println("-----------------------------------------------");
//上面的4的次数,数的,----优化----4-就是比较次数:数组长度-1次
for(int x = 0 ; x < arr.length-1;x++){//x=0,1,2,3
//x=0,0<4,
//arr.length-1-x:就是为了减少比较的次数
for(int y = 0 ;y < arr.length-1-x;y++){
//arr[0] ; y< arr.length-1-0 :第一次有0 个不比
if(arr[y] > arr[y+1]){ //arr[0] arr[1]
int temp = arr[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp;
}
}
}
System.out.println("排序之后:");
//调用遍历
printArray(arr);
System.out.println("-------------------------最终版代码---------------------------");
//使用方法来调用排序的代码--->只是排序的方法
bubbleSort(arr);
//在调用遍历功能,展示数据
printArray(arr);
}
/*
* 定义一个冒泡排序的方法:
* 两个明确
* 明确返回值类型: 没有具体返回值 --直接元素里面互换 void
* 明确参数类型 以及参数个数
* 指定数组,1个
* */
public static void bubbleSort(int[] arr){
for(int x = 0 ; x < arr.length-1;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;
}
}
}
}
/**
* 遍历数组的方法
* @param arr 对已知的数组遍历
*/
public static void printArray(int[] arr){
System.out.print("[");
//遍历数组
for(int x = 0 ; x < arr.length ; x++){
//判断:如果是最大索引值,取到最后一个元素
if(x== arr.length-1){
System.out.println(arr[x]+"]");
}else{
//中间的元素
System.out.print(arr[x]+", ");
}
}
}
面向对象
面向对象的思想特点
- 更符合现实生活中的思想行为习惯
- 让复杂的事情简单化
- 角色发生了改变:从执行者(面向过程)—>变成指挥者(面向对象)
面向对象的设计理念
不断的创建对象,使用对象,指挥对象做事情!(面对对象的宗旨)
一直用的Scanner:键盘录入
Scanner sc = new Scanner(System.in) ;
//sc.nextInt() ; sc.nextLine();
sc.nextBoolean();
面向对象的三大特征
封装,继承,多态(面向对象重点)
什么是类
类:是Java语言中最基本的单元;能够描述现实世界事物的一组事物的属性和行为的集合!
类和现实世界事物是一一对应的关系;
举例:
现实世界事物—学生事物
属性:学生的姓名,学生的年龄,学生的性别…
行为:主要就是学习
使用Java语言来描述出来的学生事物------>定一个类----学生类
class Student{
//描述学事物的属性---(代码里面--->成员变量)
//成员变量:是在类中,方法外!
String name ;
int age ;
String sex ;
//描述学事物的行为---->代码中书写--->成员方法
//今天开始写成员方法--之前怎么写,现在还怎么写,自己分析有没有具体返回值类型
//有没有参数,几个参数...
//去掉static (一般类中的成员方法:称为 "非静态方法")
public void study(String className){ //JavaEE
System.out.println("正在学习"+className) ;
}
}
什么是对象
对象:描述现实世界的具体事物!(具体事物的具体的属性和行为)
现实世界的事物—是很概括性的;
学生事物----->姓名,年龄,性别----是谁? 不知道,
需要描述具体的事物------> 具体学生 张三 25 男 / 李四 20 女
在代码中体现出来具体事物----->需要记住Java中的创建类对象的格式
创建类对象的格式:
类名 对象名 = new 类名() ;
对象名.成员变量名 = 值 (根据成员变量的类型赋值); 访问成员变量 赋值
对象名.方法名(); 访问我们自己的定义的成员方法,去使用它,展示数据或者实现具体业务需求
创建类对象的内存图解
- 创建一个类对象的内存图解
- 创建两个类对象的内存图解
- 创建多个类对象的内存图解
形式参数: 基本数据类型和引用类型 —调用该方法,实际参数?
形式参数是基本类型和引用类型,实际参数传递问题! (重点要就引用类型)
形式参数是基本类型,调用该方法,实际参数传递对应类型的数据值即可(简单,数据值传递)
形式参数是引用类型(如果是类),调用这个方法,实际参数传递需要传递当前类的具体对象 (创建类对象)
匿名对象
匿名对象: 没有名字的对象!
有名字的对象---描述具体事物 ---创建对象格式
类名 对象名 = new 类名() ;
匿名对象格式:
new 类名();
- 特点:
- 可以作为"参数传递"
- 实际用的过程,匿名对象不要多次,一般使用一次即可,使用完毕立即被回收!
在android中匿名对象使用居多 (移动端内存小,节省内存)
关于封装的概念 (重点)
private关键字的特点:可以修饰成员变量/成员方法,只能在当前类中访问,外界类不能直接访问;但是,可以间接的通过公共的方法访问
//非私有的成员变量
public int num = 20 ;
//私有的成员变量
private int num2 = 50 ;
//定义一个的公共的成员方法
public void show(){
System.out.println(num) ;
System.out.println(num2); //间接本类中的公共方法访问
}
//私有的成员方法
private void method(){
System.out.println("method Demo...");
}
//定义一个公共的成员方法
public void function(){
System.out.println("function Demo....");
method();//间接调用本类的私有方法
}
}
//测试类
public class PrivateDemo {
public static void main(String[] args) {
//要访问Demo类的num成员变量 以及num2
Demo d = new Demo() ;
System.out.println(d.num) ;
System.out.println("--------------------------");
//System.out.println(d.num2) ;num2在Demo类中已经私有控制了
d.show();
// d.method() ;//method方法已经被私有控制了
d.function();
}
}
this关键字 (重点)
this的含义: 代表当前类对象的地址值引用
this.变量名 : 访问的是本来的成员变量名
加入this---->标准类的写法 (描述学生事物/描述手机事物)
在标准类(属性私有化,对外提供公共访问setXXX(xx)/getXXX()).给成员变量赋值形式参数必须见名知意, 局部变量和成员变量名称一致,局部变量会隐藏成员变量,导致成员变量无法赋值!Java提供了关键字"this"
JavaBean规范:
1)类是具体类 class 类名{}
2)类的属性必须私有化
3)类中必须提供setXXX()/getXXX() 对成员变量的公共的访问方法(赋值/获取值)
标识符:给变量,类,接口,方法,以及常量等等起名字的一个字符序列!起名字----“见名知意”
setXXX(XXX)公共的成员方法要给成员变量赋值,里面的形式参数名称应该"见名知意"
public void setName(String name) :name就是传入姓名
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 void setGender(String g){ //"女" g
gender = g ; //"女"
}*/
public void setGender(String gender){
this.gender = gender ;
}
//获取性别的值
public String getGender(){
return gender ; //"女"
}
//其他成员方法
//行为:学习
public void study(String className){//JavaSE
System.out.println("正在学习"+className);
}
}
/*属性:姓名,年龄,性别
行为:学习
使用面向对象的编程方式来描述学生事物,并且在测试类中对学生事物进行测试--创建具体的学生对象出来!
加入封装!(将全部私有化,对外提供公共的访问方法setxxX()/getXxx())
*/
//测试类
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之面向对象");
}
}