Java学习笔记

第一二章

1.什么是JDK,JRE

  • JDK基本介绍
  1. jdk是Java开发工具包全称Java develoment kit

    JDK = JRE + java的开发工具

  2. JDK是提供给Java开发人员使用的其中包含了Java的开发工具,也包括了JRE.

    所以安装了JDK,就不用单独安装JRE了。

  • JRE基本介绍
  1. JRE (java runtime environment)也就是Java运行环境,只是运行Java而不是开发的话,只需要运行开发好的.class文件,只需要安装JRE就可以了

    JRE = JVM + java核心类库

  2. 包括Java虚拟机(JVM java virtual machine)和Java程序所需核心类库等,

    如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

2.配置环境变量path

  • 豁然开朗,因为直接输入Javac的话系统从这个目录:C:\Users\fushuo>查找,但是软件不是装在这个目录的所以查找不到,如果直接在安装目标的bin文件夹执行该命令则可以,因为java.exe就在这个路径。
  • 系统变量和环境变量的区别:系统变量范围更广,用户变量只能给该用户用。

3.Java快速入门

  • 需求说明

    开发一个Hello.java程序,可以输出“hello,world!“

  • 开发步骤

  1. 将Java代码编写到扩展名为Hello.java的文件中
    • 这个地方要注意编码格式,改完之后记得点保存
  2. 通过Javac命令对该Java文件编译,生成.class文件.class文件也叫字节码文件。
    • 运行时使用Java Hello,注意不需要加.java
    • 如果程序没有任何错误,就不会提示任何信息。
  3. 通过Java命令对生成的class文件进行运行。
  • 运行原理示意图

image-20220409152726611

  • 什么是运行
  1. 有了可执行的Java程序(hello.class字节码文件)
  2. 通过运行工具Java.exe对字节码文件进行执行。本质就是将.class文件装载到jvm中执行
  • Java程序开发注意事项
  • 对修改后的源文件需要重新编译,生成新的class文件后,再进行执行,才能生效。

4.Java开发细节

  1. Java源文件以.java为扩展名。源文件的基本组成部分是类(class),如本类中的Hello类。

  2. Java应用程序的执行入口是main()方法。他有固定的书写格式:

    public static void main(string[] args){...}

  3. java语言严格区分大小写

  4. Java方法由一条条语句构成,每个语句以分号;结束。

  5. 大括号成对出现,缺一不可,程序中每一个类在编译的时候都会对应一个.class文件

  6. 一个源文件最多只能有一个public类,其他类的个数不限

  7. 如果源文件包含一个public类,则文件名必须按该类名命名!

  8. 一个源文件中最多只能有一个public类,其他类个数不限,也可以将main方法写在非public类中然后指定运行非public类,这样入口方法就是非public的main方法

5.Java学习方法

  • 首先要有需求
  • 看看能否使用传统技术解决
  • 引出我们学习的新技术和知识点
  • 学习新技术或者知识点的基本原理和基本语法,先不要考虑细节
  • 快速入门(基本程序,curd)
  • 开始研究技术的注意事项和使用细节,使用规范,如何优化?

6.Java转义字符

image-20220409165842734

这个实例演示了Java转义字符用法,特别注意回车和换行的区别

//演示转义字符
public class ChangeChar{
	public static void main(String[] args) {
		//\t :一个制表位,实现对齐功能
		System.out.println("北京\t天津\t上海");
		//\n :换行符号
		System.out.println("jack\nsmith\nmarry");
		//\\ :一个\
		System.out.println("C:\\Windows\\System32\\cmd.exe");
		//\" :一个"
		System.out.println("老韩说:\"要好好学习Java,有前途\"");
		//\' :一个'
		System.out.println("老韩说:\'要好好学习Java,有前途\'");
		// \r :一个回车,注意,回车和换行是不一样的
		// 这个地方回车,光标定位到开头,然后执行北京,替换开头两个字
		System.out.println("世界你好,我是傅硕\r北京");
	}
}

课堂练习

//转义字符课堂练习
public class ClassTestZy{
	public static void main(String[] args) {
		System.out.println("书名\t作者\t价格\t销量\n三国\t罗贯中\t120\t1000");
	}
}

效果如图:

image-20220409172744063

7.初学Java容易犯的错误

  • 找不到文件可能原因

    • 文件名写错
    • 当前路径有问题
  • 主类名和文件名不一致

    image-20220409173623070

    解决办法:声明为public的主类名应该与文件名一致,否则编译失败

  • 缺少分号

  • 解决办法:编译失败,注意错误出现的行数,再到源代码中指定位置改错

  • 常见语法错误举例

    • 1 ->l
    • 0 ->o
    • 英文符号写成中文符号;和;
    • 拼写错误:void -> viod
    • 业务错误,环境错误

8.注释

  • Java注释类型

    • 单行注释//

    • 多行注释/**/,多行注释不允许嵌套

    • 文档注释/***/

      注释内容可以被JDK提供的工具javadoc所解析,生成一套以网页文件形式体现的该程序说明文档,一般写在类

      • 基本格式
      • 如何生成对应的文档注释
      • 应用实例
//文档注释
/**
 * @author fushuo
 * @version  1.0
 */
public class common{
	//编写一个main方法
	public static void main(String[] args){

	}
}

命令行输入:

javadoc -d D:\Users\傅硕\OneDrive\桌面\javacode\temp -author -version common.java

9.javadoc 标签

javadoc 工具软件识别以下标签:

标签 描述 示例
@author 标识一个类的作者 @author description
@deprecated 指名一个过期的类或成员 @deprecated description
{@docRoot} 指明当前文档根目录的路径 Directory Path
@exception 标志一个类抛出的异常 @exception exception-name explanation
{@inheritDoc} 从直接父类继承的注释 Inherits a comment from the immediate surperclass.
{@link} 插入一个到另一个主题的链接 {@link name text}
{@linkplain} 插入一个到另一个主题的链接,但是该链接显示纯文本字体 Inserts an in-line link to another topic.
@param 说明一个方法的参数 @param parameter-name explanation
@return 说明返回值类型 @return explanation
@see 指定一个到另一个主题的链接 @see anchor
@serial 说明一个序列化属性 @serial description
@serialData 说明通过writeObject( ) 和 writeExternal( )方法写的数据 @serialData description
@serialField 说明一个ObjectStreamField组件 @serialField name type description
@since 标记当引入一个特定的变化时 @since release
@throws 和 @exception标签一样. The @throws tag has the same meaning as the @exception tag.
{@value} 显示常量的值,该常量必须是static属性。 Displays the value of a constant, which must be a static field.
@version 指定类的版本 @version info

10.Java代码规范

  1. 类和方法的注释,要以javadoc的方式来写.
  2. 非Javadoc的注释,往往是给代码的维护者看的,着重告诉读者为什么这么写,如何修改,注意事项等
  3. 使用tab操作,实现缩进,默认整体向右边移动,使用时用shift+tab整体向左移
  4. 运算符和=两边习惯性各加一个空格.
  5. 源文件使用utf-8编码
  6. 行宽度不要超过80字符
  7. 代码编写次行风格和行尾风格

11.DOS命令

  • 查看当前目录有什么文件

dir d:\abc\test200

  • 切换到其他盘

cd /D c:

  • 切换到当前盘的其他目录下(使用相对路径和绝对路径演示)

cd d:\abc\test

cd ..\..\abc\test

  • 切换到上一级:

cd ..

  • 切换到根目录cd \

cd \

  • tree:所有子目录目录树,cls清屏,exit退出dos,md创建目录,rd删除目录,copy拷贝文件,del删除文件,echo输入内容到文件,type,move[剪切]

第三章

1.变量原理

  • 变量时程序的基本组成单位

变量有三个基本要素:类型,名称和值

如:int a = 1;定义一个变量,类型int整形,名称a,值1

2.变量使用注意事项

  1. 变量表示内存中那个一个存储区域(不同的变量,类型不同,占用的空间按大小不同,比如:int表示4个字节,double就是8个字节
  2. 该区域有自己的名称[变量名]和类型名[数据类型]
  3. 变量必须先声明,后使用,即有顺序
  4. 该区域数据可以在同一类型范围内不断变换
  5. 变量在同一个作用域内不能重名
  6. 变量=变量名+值+数据类型

3.程序中+号的使用原则

  1. 左右两边都是数值型号的时候,则做加法运算
  2. 左右两边有一方为字符串,则做拼接运算,运算顺序从左到右.
System.out.println(100 + 98);//198
System.out.println("100" + 98);//10098
System.out.println(100 + 3 + "hello");//103hello
System.out.println("hello" + 100 + 3);//hello1003

4.Java中数据类型

image-20220412195538163

5.整形类型

image-20220412200344386

  • 整形的使用细节
  1. Java个整数类型有固定的 范围和字段长度,不受具体OS影响,以保证Java程序的可移植性
  2. Java的整型常量默认为int型,声明long型常量后加l或者L
  3. Java程序中变量常声明为int型,除非不足以表示大数采用long
  4. bit,计算机中最小存储单位,byte计算机中基本存储单元,1byte= 8bit
public strtic void main(String[] args){
    int n1 = 1;
    long n2 = lL; 
}

6.浮点类型

image-20220412202640697

  • 浮点数的注意事项
  1. 与整数类型类似,Java浮点数也有固定的范围和字段长度,不受具体os的影响,[float 4个字节 double是8个字节]
  2. Java的浮点型常量默认为double型,声明float型常量,须后加f或者F

float num1 = 1.1 这样写是错误的,因为默认是double类型.

float num1 = 1.1F 这样写是正确的

double num1 = 1.1 或者是这样写

double num1 = 1.1F 这样写也是对的,因为空间是足够的

  1. 浮点型常量有两种表现形式

​ 十进制数形式如:5.12 431.0f .512(必须要有小数点)

​ 科学计数法形式:如:5.12e2[5.12 *10的二次方] 5.2E-2 [5.12 *10的负二次方]

  1. 通常情况下,应该使用double型,因为他更加精确
  2. 浮点数使用陷阱
double num11 = 2.7;
double num12 = 8.1 / 3;//2.7
System.out.println(num11);//2.7
System.out.println(num12);//接近2.7的一个数,但不是2.7
//得到的启示是,在对运算结果是小数的进行相等判断时,小心
//应该是以两个数差值的绝对值,在某个精度范围内判断
if(num11 == num12){
    System.out.println("相等");//这样写是错误的,根本不会输出这个.
}
//正确的写法
if(Matn.abs(num11 - num12) < 0.000001){
    System.out.println("equal")
}

7.java文档

  1. API(application programming interface,应用程序编程接口),是Java提供的基本编程接口(Java提供的类和相关方法).中文文档:https://www.matools.com
  2. Java语言提供了大量的基础类,API文档告诉开发者如何使用这些类,和类里面的方法

image-20220412210514492

  1. 举例说明如何使用ArrayList类有哪些方法
  • 按 包->类->方法

如果知道这个类在那个包下就先定位到包,再找到类,然后是方法.

  • 直接索引

不知道类在哪个包的情况.

8.字符类型(char)

  • 基本结束
  • 字符类型可以表示单个字符,字符类型是char,char是俩个字节(可以存放汉字),多个字符我们使用String
//演示char的基本使用
public class VarDetail{
    public static void main(String[] args){
        char c1 = 'a';
        char c2 = '\t';
        char c3 = 'han';
        char c4 = 97; //说明:字符类型可以直接存放一个数字这里输出A
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
    }
}
  • 字符常量是用单引号括起来的单个字符

char c1 = 'a';

char c2 = '中';

char c3 = "9";//这样写是错的,双引号是字符串.

  • Java允许转义字符''来将其后的字符转为特殊字符常量,例如

char c3 = '\n';

  • 在Java中,char本质是一个整数,在输出的时候是Unicode对应的字符.

  • 可以直接给char附一个整数,然后输出,按照对应的Unicode字符输出[97]

  • char类型可以进行运算,相当于一个整数,因为他都对应的有Unicode码.

  • 字符串类型本质探讨

9.编码

  • ASCII码

一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位统一规定位0,缺点是不能表示所有的值。

  • Unicode编码

一个英文字母和一个汉字都占用2个字节,这对存储空间造成了浪费,Unicode兼容ASCII码,表示最大字符是65536

  • utf-8是对Unicode的改进,根据不同符号而变化字节长度。使用大小可变的编码,字母占一个字节,汉字占3个字节。

10.布尔类型

  • 基本介绍
  1. 布尔类型只允许取值true和false,无null
  2. 布尔类型占一个字节。
  3. 布尔类型适用于逻辑运算,一般用于程序流程控制
    • if条件控制语句;
    • while循环语句
    • do-while循环控制语句
    • for循环控制语句
public class Boolean{
    public static void main(String[] args){
        //演示判断成绩是否通过
        //定义一个布尔变量
        boolean inPass = true;
        if(isPass == true){
            System.out.println("考试通过,恭喜");
        }else{
            System.out.println("考试没有通过,下次努力");
        }
    }
}
4. 使用细节

不可以用非0的整数替代false和true这点和c语言不同。

11.基本数据类型转换

  • 自动类型转换

Java程序进行赋值或者运算的时候,精度小的类型自动转换为精度大的数据类型,这个就是自动转换类型

数据类型按精度大小排序位这个要记住

  • char->int->long->float->double

  • byte->short->int->long-float-double

int a = 'c';//这个是对的
double d = 80;//这个是对的
  • 自动类型转换注意和细节
  1. 有多种的数据混合运算时,系统首先将所有数据转换为容量最大的那种数据类型,然后进行计算。
  2. 当我们把精度大(容量大)的数据类型赋值给精度小的的数据类型时,就会报错,反之就会进行自动类型转换。
  3. 注意byte,short和char之间不会进行相互转化。
  4. byte,short,char他们三者可以计算,在计算时首先转换为int类型
  5. Boolean类型不参与类型转换
  6. 自动提示原则:表达式结果自动提升为操作数中最大的类型
public class AutoConvertDetail{
    public static void main(String[] args){
        int n1 = 10;
        double d1 = n1 + 1.1;//注意1.1默认位double类型,
        float d1 = n1 + 1.1;//这样写时错误的因为1.1时double类型,1.1f才是float类型。
        
        int n2 = 1.1;//错误,double不能转为int
        //(byte,short)和char不发生类型转换
        //当把数赋给byte时,先判断数是否在byte范围内,如果是就可以
        byte b1 = 10;//对,-128,-127先判断类型
        int n2 = 1;
        byte b2 = n2;//这样是不行的,因为n2已经是int类型了
        char c1 = b1;//错误,原因是byte不能自动转成char
        //出现了short,char,byte中任何一个,精度就会提升。
        byte b2 = 1;
        byte b3 = 1;
        short s2 = 1;
        short s2 = b2 + s1;//错,b2+s1->int
        byte b4 = b2 + b3;//错,b2 + b2 ->int
    }
}

12.强制类型转换

  • 介绍
  • 自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型,使用时要加上强制转换符(),但可能造成精度降低或溢出,格外注意。
public class ForceConvert{
    public static void main(String[] args){
        //演示强制转换类型
        int n1 = (int)1.9;
        System.out.println("n1=" + n1);
        
        int n2 = 2000;
        byte b1 = (byte)n2;//数据超过了byte范围-127,128
        System.out.println("b1"+b1);
        
    }
}
  • 强制转换的细节说明
  1. 进行数据的大小从大——>小就需要使用到强制转换
  2. 强制符号只针对最近的操作数有效,往往会使用小括号提升优先级
int x = (int)10*3.5 + 1.5*6//这样写会报错,因为强转符号只针对最近的操作数有效。
int x = (int)(10*3.5 + 6*1.5)//这样就是正确的。
  1. char类型可以保存int的常量值,但不能保存int的变量值,需要强转
char c1 = 100;//ok
int m = 100;//ok
char c2 = m;//错误,int精度大
char c3 = (char)m;//可以,这是强转

  • 基本数据类型转换练习题

判断下列语句能否通过编译:

short s = 12;//不可以,9是int类型,s是short无法赋值,必须强制类型转换
s = s-9;
//----------
byte b = 10;//不可以,理由同上
b = b + 11;
b = (byte)(b+11);
//----------
char c = 'a';//可以,自动转为精度最大的float,doule可以接受float
int i = 16;
float d = .314F;
double result = c + i + d;
//----------
byte b = 16;//不可以,只要有byte,short和char参与运算一律提升了精度为int
short s = 14;
short t = s + b;

13.基本类型和String类型的转换

  • 基本类型转String加双引号就可以
int n1 = 100;
float f1 = 1.1F;
double d1 = 1.4;
boolean b1 = true;
//--------------
String s1 = n1 + "";
String s2 = f1 + "";
String s3 = d1 + "";
String s4 = n1 + "";
String s5 = "123"
System.out.println(s1+" "+s2+" "+s3+" "+s4);
  • 字符串转为基本类型
  1. 语法:通过基本类型的包装类调用parsexx方法即可
String s5 = "123";
int num1 = Integer.parseInt(s5);
double num2 = Double.parseDouble(s5);
float num3 = Float.parseFloat(s5);
long num4 = Long.parseLong(s5);
byte num5 = Byte.parseByte(s5);
byte num5 = Boolean.parseBoolean("true");
short num6 = short.parseShort(s5);
//字符串转为字符:就是把字符串第一个字符取出
s5.charAt(0);//解读:就是将s5字符串的第一个字符返回。得到的是字符不是数字。

  1. 注意事项

在把String类型转为基本数据类型的时候,确保,String类型能够转为有效的数据,比如不能把“hello"转为一个整数,如果格式不正确,就会抛出异常。

14.本章作业

  • 使用char类型,分别保存\n \r \r \ 1 2 3等字符,并打印输出
public class Homework02.java{
    public static void main(String[] args){
        char c1 = '\n';
        char c2 = '\t';
        char c3 = '\\';
        char c4 = '1';
        char c5 = '2';
        char c6 = '3';
        System.out.println(c1);
    }
}
  • 编程,保存两个书名,用+拼接,看效果,保存两个性别,用加号拼接,看效果。保存两本书价格,用加号拼接看效果
public class HomeWork03{
    public static void main(String[] args){
        String s1 = "老人与海";
        String s2 = "骆驼祥子";
        char sex1  = "男";
        char sex2 = "女";
        double price1 = 10;
        double price2 = 11;
        System.out.println(s1+s2);
        System.out.println(sex1 + sex2);//得到男字符值+女字符值
        Syste.out.println(price1+price2);
    }
}
  • 编程实现如下效果Homework04.java
public class Homework04{
    public static void main(String[] args){
        String name = "fushuo";
        char gender = "男";
        String hobby = "read";
        double score = 100.0;
        int age = 22;
        System.out.println("姓名\t年龄\t成绩\t性别\t爱好\n"+name+"\t"+age+"\t"+score+"\t"+gender+"\t"+hobby)
    }
}

第四章运算符

1.运算符介绍

  • 算数运算符

    对数值型运算

image-20220418204720433

public class ArithmeticOperator{
    public static void main(Strint[] args){
        //演示算术运算符的使用
        // /的使用
        System.out.println(10 / 4);//等于2.不是2.5
        double d = 10 / 4;
        System.out.println(d);//等于2.0而不是2,也不是2.5
        System.out.println(10.0/4);//等于2.5
        //-----------
        //取模的使用
        //%的本质是a%b = a-a/b*b
        System.out.println(10%3);//1
        System.out.println(-10%3);//-1
        System.out.println(10%-3);//1
        System.out.println(-10%-3);//-1
        //---------------
        //++的使用
        int i = 10;
        //如果作为独立语句使用前置加加和后置加加一样
        i++;
        ++i;
        //作为表达式使用,++i先自增后赋值i++先赋值后自增
        int j = 8;
        int k = ++j;
        int m = j++;
        System.out.println("k=" + k + "j=" +j);
    }
}
  • 面试题
//面试题1
int i = 1;
i = i++;//使用临时变量,temp = i;->i = i+1;->i = temp
System.out.println(i);//结果是1
//面试题2
int i = 1;
i = ++i;//使用临时变量,i = i+1->temp = i;->i = temp
System.out.println(i);//结果是2
//面试题3
int i1 = 10;
int i2 = 20;
int i = i1++;
System.out.println("i="+i);//10
System.out.println("i2="+i2);//20
i = --i2;
System.out.println("i="+i);//19
System.out.println("i2="+i2);//19

假如还有59天放假,问:合xx个星期零xx天

public class ArithmeticOperatorExercise02{
    public static void main(String[] args){
        /*
        思路分析
        1.使用int变量days保存天数
        2.一个星期是7天,星期数:days/7零xx天days%7
        3.输出
        */
        int days = 59;
        int weeks = days/7;
        int leftDays = days%7;
        System.out.println(days+"天 合" + weeks + "星期零"+leftDays+"天")
    }
}

定义一个变量保存华氏温度,华氏温度转换摄氏温度公式为5/9*(华氏温度-100),请求出华氏温度对应地摄氏温度

public class ArithmeticOperatorExercise03{
    public static void main(String[] args){
        double f = 44.2;
        double c = 5.0/9*(f-100);//注意不可以是5,不然返回0!!!!!!因为5/9=0
        System.out.println("华氏温度:"+f+"对应的摄氏温度:"+c);
    }
}

2.关系运算符

  • 关系运算符一览

image-20220419210948139

关系运算符的相关案例

  • 案例演示
public class RelationalOperator{
    public static void main(String[] args){
        int a = 9;
        int b = 8;
        System.out.println(a>b);//T
        System.out.println(a>=b);//T
        System.out.println(a<=b);//F
        System.out.println(a<b);//F
        System.out.println(a == b);//F
        System.out.println(a!=b);//T
        boolean flag = a>b;//T
        System.out.println(flag)//T
    }
}

3.逻辑运算符

image-20220419211657421

image-20220419211911743

  • 短路与&&和逻辑与&的基本规则
public class LogicOperator{
    public static void main(String[] args){
        //&&和&的使用
        int age = 50;
        if(age > 20 && age < 90){
            System.out.println("ok100");
        }
        if(age > 20 & age < 90){
            System.out.println("ok100");
        }
    }
}
  • 短路与&&和逻辑与&的区别

&&:如果第一个条件false,第二个条件不会判断,最终条件false,效率高

&:逻辑与,不管第一个条件是否为false,第二个条件都会判断,效率低

开发中基本使用&&,效率高

  • 短路或||和逻辑或|

短路或:如果第一个条件是true那么第二个条件不会判断,效率较高,逻辑或,不管第一个条件是否为true第二个条件都会判断。

  • 取反!

4.逻辑运算符练习题

int x = 5;
int y = 5;
if(x++==6 & ++y==6){
    x = 11;
}
System.out.println("x="+x+",y="+y);x:6,y:6
//--------
int x = 5,y = 5;
if(x++==5 | ++y==5){
    x = 11;
}
System.out.println("x="+x+",y="+y);x:11,y:6
//--------
int x = 5,y = 5;
if(x++==6 && ++y==6){
    x = 11;
}
System.out.println("x="+x+",y="+y);x:6,y:5
//----------
int x = 5,y = 5;
if(x++==5 || ++y==5){
    x = 11;
}
System.out.println("x="+x+",y="+y);x:11,y:5
//-----------
boolean x = true;
boolean y = false;
short z = 46;
if((z++==46)&&(y=true)) z++;//注意y=true赋值语句
if((x=false)||(++z==49)) z++;
System.out.println("z="+z);//输出z:50

5.赋值运算符

  • 介绍

赋值运算符就是将某个运算后的值,赋给指定的变量

  • 分类

    • 基本赋值运算符:int a = 10;
    • 复合赋值运算符
      • +=,-=,*=,/=,%=等
      • a += b;等价于a = a+b
  • 赋值运算符的特点

    1. 运算顺序从右向左,int num = a+b+c;
    2. 赋值运算符的左边只能是变量,右边可以是变量表达式和常量值

    int num = 20;int num2 = 78*34-10;int num3 = a;

    1. 复合赋值运算等价于下面的效果

      比如:a+=3 等价于a=a+3

    2. 复合赋值运算符会进行类型转换。

      byte b = 2;b+=3;b++;

int n1 = 10;
n1 += 4;//14
n1 /= 4;// 3
//复合赋值运算符会进行类型转换
byte b = 3;
b += 2;//真正等价于b = (byte)(b+2)因为b = b + 2会报错(精度提升)
//同样
b++;//底层也有类型转换b = (byte)(b+1)

6.三元运算符

  • 基本语法

条件表达式?表达式1:表达式2;

运算规则

  1. 如果条件表达式为true,运算后的结果是表达式1;
  2. 如果条件表达式的结果是false,运算后的结果是表达式2;
  3. 口诀:[一灯大师:一真大师]
int a = 10;
int b = 99;
int result = a>b?a++:b--;//先返回b然后自减,返回的结果是99而不是98
  • 三元运算符的使用细节

    1. 表达式1和表达式2要为可以赋给接收变量的类型(或可以自动转换)
int a = 3;
int b = 8;
int c = a > b ? (int)1.1 : (int)3.4;//强转类型才能匹配
double d = a > b ? a : b + 3;//可以的,double可以接受int
1. 三元运算符可以转成if--else语句

int res = a>b ? a++ : --b;

  • 课堂练习

案例:实现三个数的最大值

public class TernaryOperatorExerise{
    public static void main(String[] args){
        int n1 = 55;
        int n2 = 33;
        int n3 = 123;
        //思路
        //先得到n1和n2中最大数,保存到max1,然后和n2比较
        int max1 = n1 > n2 ? n1:n2;
        int max = max1 > n3 ? max1:n3;
        System.out.println(max);
        //尝试使用一条语句实现,可以这样写,但是不清晰,后面还可以使用更好的方法解决
    }
}

7.运算符的优先级问题

  • 运算符有不同的优先级,所谓优先级就是表达式运算中运算顺序,只有单目运算符和赋值运算符是从右向左运算的。运算符运算顺序如下图所示,优先级从上而下:

image-20220421204733551

8.标识符的命名规则和规范

  • 标识符的概念
  1. Java对各种变量,方法和类等命名的时候使用的字符序列称为标识符
  2. 凡是自己可以起名字的地方都叫标识符int num1 = 90;
  • 标识符的命名规则(必须遵守)
  1. 由26个英文字符大小写0-9,或<span data-formula="组成
  2. 数字不可以开头,
  3. 不可以使用关键字和保留字,但能包含关键字和保留字
  4. Java中严格区分大小写,长度无限制," aria-hidden="true">组成
  5. 数字不可以开头,
  6. 不可以使用关键字和保留字,但能包含关键字和保留字
  7. Java中严格区分大小写,长度无限制,int totalNum = 10;int n = 90
  8. 标识符不能包含空格
  • 标识符的命名规范
  1. 包名:多单词组成时,所有字母小写,:aaa.bbb.ccc//比如com.hsp.crm
  2. 类名、接口名:多单词组成时,所有的单词首字母大写:XxxYyyZzz(大驼峰法)

​ 比如:ThankShotGame

  1. 变量名、方法名:多单词组成的时候,第一个单词首字母小写,第二个单词开始买个单词首字母大写:xxxYyyZzz(小驼峰,简称驼峰法)

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

    ​ 比如:定义一个税率TAX_RATE

  3. 后面我们学习到类,包,接口等,我们命名规范要这样遵守,更加详细看文档

9.Java关键字

  • 定义:被Java语言赋予了特殊含义,用作专门用途的字符串(单词)
  • 特点:关键字中所有字母都为小写

image-20220421212453643

image-20220421212547708

  • 保留字

image-20220421212649200

10.键盘输入语句

  • 介绍

键盘输入语句需要一个扫描器(对象),就是Scanner

  • 步骤
  1. 导入该类的所在包,java.util.*
  2. 创建该类对象(声明变量)
  3. 调用里面的功能
//案例演示
import java.util.Scanner//表示把java.util下的Scanner类导入
public class Input{
    public static void main(String[] args){
        //演示接受用户的输入
        //步骤
        //Scanner 类 表示简单文本扫描器,在java.util包
        //1.引入/导入 Scanner类所在的包
        //2.创建Scanner对象
        Scanner myScanner = new Scanner(System.in);
        //3.接受用户输入
        System.out.println("请输入名字");
        String name = myScanner.next();//接受用户输入字符串
        System.out.println("请输入年龄");
        int age = myScanner.nextInt();//接受用户输入int
        System.out.println("请输入薪水");
        double sal = myScanner.nextDouble();//接受用户double
        System.out.println("人的信息如下:");
        System.out.println("name="+name+"age="+age+"sal");
        
    }
}

11.进制

  • 进制介绍
  1. 二进制:0,1满2进1.以0b或者0B开头
  2. 十进制:0-9,
  3. 八进制:0-7,满8进一。以数字0开头表示
  4. 十六进制:0-9以及a-f,或者A-F-以0x或者0X开头
int n1 = 0b1010;
int n2 = 1010;
int n3 = 01010;
int n4 = 0x10101;
  • 进制转换
  • 位运算的思考题
public static void main(String[] args){
    int a = 1>>2;//1向右位移两位
    int b = -1>>2;
    int c = 1<<2;//
    int d = -1<<2;//
    int e = 3 >>> 2;//无符号右移
    //a b c d e结果各是多少
}
~2 = ?;//按位取反
2&3 = ?;//按位与
2|3 = ?;//按位或
~-5=?;
13&7 = ?;
5|4 = ?;
-3^3 = ?//^按位异或

12.位运算符

  • Java中有7个位运算(& | ^ ~ >> << >>>)
  • 分别是按位与&、按位或|按位异或^按位取反~运算规则如下:

按位与&:两位全为1,结果为1,否则0

按位或|:两位有一个是1,结果是1,否则0

按位异或^:两位一个为0,一个为1,结果为1,否则0

按位取反~:0->1,1->0

比如:2&3=? ~-2 = ? ~2=?

image-20220425205711354

image-20220425210111803

image-20220425210350394

  • 还有三个位运算符>> <<和>>>运算规则如下:
  1. 算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位本质

int a = 1>>2 相当于1/2/2 = 0

  1. 算术左移<<:符号位不变,低位补0

int c = 1 << 2 相当于1*2 *2 = 4

  1. >>>逻辑右移也叫无符号右移,运算规则:低位溢出,高位补0
  2. 特别说明:没有<<<符号

13.本章作业

  • 计算下列表达式的值
10/3	3
10/5	3
10%2	0
//注意小数的取模运算
-10.5%3 -1.5//a%b 当a是小数时,公式= a -(int)a/b*b
int i = 66;
System.out.println(++i+i);//打印134
  • 以下赋值语句正确的是
int num1 = (int)"18";//错误,要用包装类Interger.parseInt("18")
int num2 = 18.0;//错误
double num3 = 3d;//正确
double num4 = 8;//正确
int i = 49;char ch = i+1;t;//错误,尝试把int变成char
byte b = 19;short s = b+2;//错误,int-short
  • 试着写出将String转换位double类型的语句,以及将char类型转换成String的语句
double d = Double.parseDouble("13.2");
char c1 = 'd';
String x = c1 + ""

第五章控制结构

1.顺序控制

程序从上到下逐行执行,中间没有任何判断和跳转

2.分支控制if-else

  • 单分支

基本语法:

if(条件表达式){

​ 执行代码块:(可以有多条语句)

}

说明:当条件表达式为true时,就会执行{}的代码。如果是false,就不执行。

特别说明,如果{}中只有一条语句,则可以不用{},但是建议写上{}

//案例说明,编写一个程序,可以输入人的年龄,如果年龄大于18岁,则输出,你的年龄大于18,要对自己的行为负责
import java.utils.Scanner;
public class If01{
    public static void main(String[] args){
        //思路分析
        //接受输入的年龄,应该定义一个Scanner对象
        //把年龄保存到一个变量int age
        //使用if判断,输出信息
        Scanner myScanner = new Scanner(System.in);
        System.out.println("请输入年龄");
        int age = myScanner.nextInt();
        if (age >= 18){
            System.out.println("你的年龄大于18,你要对自己的行为负责")
        }
    }
}
  • 双分支

基本语法

if(条件表达式){

执行代码块1;

}

else{

执行代码块2;

}

说明:当条件表达式成立,即执行代码块1,否则执行代码块2,如果执行代码块只有一条语句则{}可以省略,否则不可以省略。

案例演示

import java.util.Scanner;
public class If02{
    publci static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        System.out.println("请输入年龄");
        int age = myScanner.nextInt();
        if(age >= 18){
            System.out.println("你的年龄大于18")
        }else{
            System.out.println("你的年龄不大")
        }
    }
}
  • 分支控制练习题
//单分支和双分支练习题
//对下列代码,若有输出,指出输出结果
int x = 7;
int y = 4;
if(x > 5){
    if(y>5){
        System.out.println(x+y);    
    }
    System.out.println("韩顺平教育");
}else
    System.out.println("x is" + x);
//输出内容是:
//韩顺平教育
//编写程序,声明两个double变量并赋值,判断第一个数大于10.0,第二个数小于20.0,打印两数之和
public class IfExercise2{
    public static void main(String[] args){
        double x = 18.0;
        double y = 3.0;
        if(x>10.0 && y<20){
            System.out.println("x+y="+(x+y))
        }
    }
}
//定义两个变量int判断二者之和,是否能被3又能被5整除,打印提示信息
public class IfExercise3{
    public static void main(String[] args){
        int x = 8;
        int y = 4;
        int z = x + y;
        if(z%3==0&&z%5==0){
            System.out.println(x+"和"+y"的和既可以被3又可以被5整除");
        }else{
            System.out.println(x+"和"+y"的和不能同时被3又可以被5整除");
        }
    }
}
//判断一个年份是否是闰年,闰年的条件时符合下面二者之一:
//年份能被4整除,但不能被100整除
//能被400整除
import java.util.Scanner;
public class IfExercise3{
    public static void main(String[] args){
        Scanner myYear = new Scanner(System.in);
        System.out.println("请输入一个年份");
        int year = myYear.nextInt();
        if (year%400 ==0||(year%4==0&&year%100!=0){
            System.out.println(year+"年是闰年");
        }else{
            System.out.println(year+"年不是润年");
        }
    }
}
  • 多分支控制

案例演示

输入保国同志的芝麻信用分:

如果:

1信用分为100分时,输出信用极好

2信用分为(80,99)时输出信用优秀

3信用分为(60,80)时输出信用一般

4其他情况,输出信用不及格

5从键盘输入报国的芝麻信用分,并加以判断

import java.util.Scanner;
public class If3{
    public static void main(String[] args){
        Scanner my = new Scanner(System.in);
        System.out.println("请输入你的芝麻信用分!");
        int score = my.nextInt();
        //先对输入信用分,进行一个有效判断,进行有效判断,否则提示输入错误
        if(score >=1 && score <= 100){
            if(score == 100){
                System.out.println("信用良好");
            }else if(score >80 && score <= 99 ){
                System.out.println("信用优秀");
            }else if(score > 60 && score <= 80 ){
                System.out.println("信用一般")
            }else{
                System.out.println("信用不及格")
            }
        }else{
            System.out.println("信用分需要在1-100,请重新输入")
        }
    }
}

案例演示2

看看代码输出什么?

boolean b = true;
if(b == false)
    System.out.println("a");//如果改成b=false编译可以通过
else if(b)
    System.out.println("b");//b
else if(!b)
    System.out.println("c");
else
    System.out.println("d");

3.嵌套分支

  • 基本介绍

在一个分支结构中完整的嵌套了另一个分支结构,里面的分支结构成为内层分支,外面的分支结构成为外层分支,但是嵌套不要超过三层(可读性不好)

  • 基本语法
if(){
    if(){
        //if else
    }else{
        //if-else
    }
}

应用案例 参加歌手比赛,如果初赛成绩大于8进入决赛,否则提示淘汰,并且根据性别提示进入男子组或者女子组 可以让学员先练习一下,输入成绩和性别,进行判断和输出信息

import java.util.Scanner;
public class NestedIf.java{
    public static void main(String[] args){
        Scanner myInput = new Scanner(System.in);
        System.output.println("请输入成绩");
        double score = myInput.nextDouble();
        System.output.println("请输入性别");
        char gender = myInput.next().charAt(0);
        if (score < 8.0){
            System.out.println("你已经被淘汰");
        }else{
            if (gender == '男'){
                System.out.println("你进入男子组比赛");
            }else{
                System.out.println("你进入女子组比赛");
            }
        }
    }
}

嵌套分支的练习题 要求: 出票系统,根据淡旺季的月份和年龄,打印票价 旺季(4-10):城人(18-60):60 儿童(<18):半价 老人(>60):1/3 淡季: 成人:40 其他:20

import java.util.Scanner;
public class If{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        System.out.println("请输入月份");
        int month = myScanner.nextInt();
        System.out.println("请输入年龄");
        int age = myScanner.nextInt();
        if (month >=4 && month <= 10){
            if (age>60){
                System.out.println("你的票价为20元");
            }else if (age < 18){
                System.out.println("你的票价为"+60/2+"元");
            }else{
                System.out.println("你的票价为60元");
            }
        }else{
            if (age < 18){
                System.out.println("你的票价为20元");

            }else{
                System.out.println("你的票价为40元");
            }
        }
    }
}

4.switch分支结构

  • 快速入门

案例: 编写一个程序,该程序可以接收一个字符,a,b,c,d,e,f,g a表示星期一,b表示星期二 根据用户输入显示相应的信息。要求使用switch语句完成

import java.util.Scanner;
public class Switch01{
    public static void main(String[] args){
        Scanner.out.println("请输入一个字符(a-g)");
        Scanner myScanner = new Scanner(System.in);
        char ch = myScanner.next().charAt(0);//在Java中只要有值返回就是一个表达式
        stitch(ch){
            case 'a':
            System.out.println("今天是星期一");
            break;
            case 'b':
            System.out.println("今天是星期二");
            .......
            default:
            System.out.println("你输入的信息不匹配");
        }
    }
}
  • switch注意事项和细节讨论
  1. 表达式数据类型,应和case后的常量类型一致,或者是可以自动转换成可以相互比较的类型,比如输入的是字符,而常量是int
public class SwitchDetail{
    public static void main(String[] args){
        char c = 'a';
        switch(c){
            case 'a':
            System.out.println("do");
            break;
            case "dddd"://和表达式类型不匹配,而且无法转换
            System.out.println("dd");
            break;
            case '20'://可以的,应为char可以转换为int
            System.out.println("sd");
            default:
            System.out.println("dd");
        }
    }
}
  1. switch表达式中返回值必须是(byte,short,int,char,enum,String)
double c = 1.0;
switch(c){
    case 1.0://错误

}
  1. case子句中的值必须是常量,而不能是变量
  2. default子句是可选的,当没有匹配的case时,执行default
  3. break语句用来执行完一个case分支后使得程序跳出switch语句块,如果没有break,程序会顺序执行到switch结尾,并不会判断,直接穿透

课堂练习 SwitchExercise.java

  1. 使用switch把小写的char类型转为大写(键盘输入),只转换a,b,c,d,e其他的输入other
  2. 对学生成绩大于60的输出合格,低于60的,输出不合格,(输入的成绩不能大于100),提示成绩/60
  3. 根据用于指定月份,打印该月所属的季节,3,4,5春季,6,7,8夏季,9,10,11秋季,12,1,2,冬季(提示:使用穿透) 题目1:
import java.util.Scanner;
public class SwitchExercise{
    public static void main(String[] args){
     Scanner myScanner = new Scanner(system.in);
     System.out.println("请输入字符");
     char ch = Scanner.next().charAt(0);
     switch (ch){
         case 'a':
         ch = 'A';
         break;
         case 'b':
         ch = 'B';
         break;
         case 'c':
         ch = 'C';
         break;
         case 'd':
         ch = 'D';
         break;
         case 'e':
         ch = 'E';
         break;
         default:
         System.out.println("other");
     }
    }
}

题目2:

import java.util.Scanner;
public class SwitchExercise02{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        System.out.println("请输入学生成绩");
        int score = myScanner.nextInt();
        if (score <=100 && score >=0){
            switch (score/60){
                case 0:
                System.out.println("成绩不合格");
                break;
                case 1:
                System.out.println("成绩合格");

            }
        }else{
            System.out.println("你的输入有误请重新输入");
        }
    }
}

题目3:

import java.util.Scanner;
public class SwitchExercise03{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int month = myScanner.nextInt();
        switch (month/3){
            case 1:
            System.out.println("春季");
            break;
            case 2:
            System.out.println("夏季");
            break;
            case 3:
            System.out.println("春季");
            break;
            default:
            System.out.println("冬季");
        }
    }
}

题目3另一种解答(利用穿透)

import java.util.Scanner;
public class SwitchExercise03{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int month = myScanner.nextInt();
        switch (month/3){
            case 3:
            case 4:
            case 5:
            System.out.println("春季");
            break;
            case 6:
            case 7:
            case 8:
            System.out.println("夏季");
            break;
            case 9:
            case 10:
            case 11:
            System.out.println("秋季");
            break;
            case 12:
            case 1:
            case 2:
            System.out.println("冬季");
            default:
            System.out.println("输入有误");
        }
    }
}
  • switch和if的比较

如果判断的具体数值不多而且更符合byte,short,int,char,enum,String这两种类型,虽然两种语句都可以说hi用但是更建议使用switch语句

其他情况,对区间判断,对结果为Boolean类型判断使用if

5.for循环控制

  • 注意事项和细节说明
  1. 循环条件是返回一个布尔值的表达式
  2. for(;循环判断条件;)中的初始化和变量迭代可以写到其他地方,但是两边分号不能省略,下面这种写法也是可以的,下面这种写法,适用于循环结束后仍然想使用到i的情况,要注意的是写在循环体内的i作用域仅限循环
int i = 1;
for(; i <= 10 ;){
    System.out.println("你好");
    i++;
}
  1. 循环初始化可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代语句,中间用逗号隔开。
  2. 使用内存分析法,分析下面输出
int count = 3;
for(int i = 0,j = 0;i < count;i++,j += 2){
    System.out.println("i=" + i + "j=" +j);
}//输出00 12 24
  1. 注意for(;;)表示无限循环,配合break

for循环控制练习 1.打印1~100之间所有9的倍数的整数,统计个数,以及总和(化繁为简,先死后或)

public class ForExercise{
    public static void main(String[] args){
        int sum = 0;
        int count = 0;
        for(int i = 0 ;i <=100 ;i++){
            if(i % 9 == 0){
                System.out.println("i="i);
                count++;
                sum += i;//累积
            }
        }
    }
}

6.while循环控制

  • 基本语法

循环变量初始化; while(循环条件){ 循环体(语句); 循环变量迭代; }

  • 说明
    • while循环也有四要素
    • 只是四要素的位置不一样,
//while循环的案例
public class While01{
    public static void main(String[] args){
        int i = 1;//循环变量初始化
        while(i <= 10 ){
            System.out.println("你好"+i);
            i++;
        }
        System.out.println("退出循环");
    }
}

while循环的练习题

public class WhileExercise{
    public static void main(String[] args){
        int i = 1
        while(i <= 100){
            if(i%3==0){
                System.out.println("i="+i);
            }
            i++;
        }
        System.out.println("退出循环");
    }
}
public class WhileExercise2{
    public static void main(String[] args){
        int i = 40;
        while(i<=200){
            if (i%2==0){
                System.out.println(i);
            }
            i++;
        }
    }
}

7.do while循环

  • 基本语法

循环变量初始化 do{ 循环体(语句); 循环变量迭代; }while(循环条件);

  • 说明
  1. do while 都是关键字
  2. 也有循环四要素,只是位置不一样
  3. 先执行,再判断,也就是说,一定会执行一次
  4. 最后有一个分号
  5. while和do while区别举例:要账 输出十句hello word
int i = 1;//循环变量初始化
do{
    //循环执行语句
    System.out.println("你好,世界"+i);
    //循环变量迭代
    i++;
}while(i <= 10);
System.out.println("退出循环")

课堂练习题

  1. 打印1-100
public class DoWhileExercise{
    public static void main(String[] args){
        int i = 1;
        do{
            System.out.println("i="+i);
            i++;
        }while(i <= 100);
    }
}
  1. 计算1-100的和
public class DoWhileExercise02{
    public static void main(String[] args){
        int i = 1;
        int sum = 0;
        do{
            sum += i;
            i++;
        }while(i <= 100);
        System.out.println(sum);
    }
}
  1. 统计1-200之间能被5整除但不能被3整除的个数
public class DoWhileExercise{
    public static void main(String[] args){
        int i = 1;
        int sum = 0;
        do{
            if(i % 5 == 0 && i % 3 != 0){
                System.out.println(i);
            }
        }while( i <= 200);
    }
}
  1. 如果李三不还钱,老韩一直使出五连鞭,直到李三还钱为止。
import java.util.Scanner;
public class DoWhileExercise{
    public static void main(String[] args){
        //不停的问还钱吗?
        //使用char answer接受回答
        //在do-while的while判断如果是y就不在循环。
        char answer = ' ';
        Scanner myScanner = new Scanner(System.in);
        do{
            System.out.println("老韩使出五连鞭");
            System.out.println("老韩问:还钱吗?y/n");
            answer = myScanner.next().charAt(0);
            System.out.println("他的回答是:"+answer);
        }while(answer != 'y');
    }
}

8.多重循环

多重循环执行步骤分析:

//双重for
for(int i = 0;i < 2 ;i++){
    for(int j = 0;j<3;j++){
        System.out.println("i=" + i + "j=" + j);
    }
}

多重循环控制应用实例

  1. 统计3个班成绩情况,每个班有5名同学,求出各个班的平均分和所有班级的平均分(学生成绩从键盘输入)
  2. 统计三个班及格人数,每个班有5名同学。
  3. 打印出九九乘法表
import java.util.Scanner;
public class MulForExercise{
    public static void main(String[] args){
        double avgScore = 0;
        double sumScore = 0;
        int count = 0;//累计及格人数
        Scanner myScanner = new Scanner(System.in);
        for(int i = 0;i < 3;i++){
            for(int j = 0;j < 5;j++){
                double score = 0;
                System.out.println("请输入第"+(i+1)+"个班级,第"+(j+1)+"个学生的成绩");
                score = myScanner.nextDouble();
                System.out.println("输入完成");
                sumScore += score;
                if(score > =60){
                    count += 1;
                }
            }
            System.out.println("该班级所有学生的平均成绩为"+sumScore/5+"分");
        }
        avgScore = sumScore/15;
        System.out.println("三个班级的平均成绩为"+avgScore);
    }
}

public class MulFor{
    public static void main(String[] args){
        for(i=1;i<=9;i++){
            for(j=1;j<=9;j++){

            }
        }
    }
}

多从循环控制练习题

  1. 经典的打印金字塔 使用for循环
public class Stars{
    public static void main(String[] args){
        for(int i = 1;i<=5;i++){
        	for(int k=1;k<=5-i;k++){
        		System.out.print(' ');
        	}
            for(int j=1;j<=2*i-1;j++){
                System.out.print('*');
            }
            System.out.print('\n');
        }
    }
}
public class Stars{
    public static void main(String[] args){
        for(int i = 1;i<=5;i++){
        	for(int k=1;k<=5-i;k++){
        		System.out.print(' ');
        	}
            for(int j=1;j<=2*i-1;j++){
                if(j==1||j==2*i-1||i==5){
                    System.out.print("*");
                }else{
                    System.out.print(" ");
                }
            }
            System.out.print('\n');
        }
    }
}

9.跳转语句break

  • 快速入门
for(int i=0;i<=10;i++){
    if(i == 3){break;}
    System.out.println("ok"+i);
}

需求:随机生成1-100的一个数,直到生成97,看看你一共用了多少次? 提示:使用(int)(Math.random()*100)+1 思路分析:

public class Break{
    public static void main(String[] args){
        int count = 0;
        while(true){
            count = count+1;
            int num = (int)(Math.random()*100)+1;
            if(num == 97){break;}
        }
        System.out.println("一共用了"+count+"次猜中");
    }
}

注意事项和细节说明:

  1. break语句出现在多层嵌套的语句中可以通过标签指明要终止的是哪一层语句块

  • 课堂练习题

    1. 1-100以内的数求和,求出当和第一次大于20的当前数(for+break)
    2. 实现登录验证,有三次机会,如果用户名为”丁真“,密码为”666“提示登陆成功否则提示还有几次机会,请使用for+break完成
public class BreakExercise{
    public static void main(String[] args){
        int count = 0;
        for(int i = 1;i<=100;i++){
            count = count + 1;
            if(count > 20){break;x = i;}
    aaa    }
        System.out.println("当和第一次大于20时,当前数为"+x);
    }
}
import java.util.Scanner;
public class BreakExercise02{
    public static void main(String[] args){
    int count = 3;
    Scanner myScanner = new Scanner(System.in);

    for(int i = 1;i<=3;i++){
        System.out.println("请输入用户名和密码。");
        String username = myScanner.next();
        String password = myScanner.next();
        if("丁真".equals(username) && "666".equals(password)){
            System.out.println("登录成功");
            break;
        }else{
            System.out.println("登录失败,你还有"+(3-i)+"次机会");
            
        }
    }  
    }
}

10.跳转语句continue

  • 基本结束:

    1. continue语句用于结束本次循环,继续执行 下一循环。
    2. continue语句出现在多层嵌套的循环语句体中,可以通过标签指明要跳过的是那一层循环,这个和前面的标签使用规则一样。
  • 基本语法:

{ ... continue; ... } ddd 例子:

public class Continue01{
    //编写一个main方法
    public static void main(String[] args){
        //代码
        int i = 1;
        while( i <= 4){
            i++;
            if( i == 2){
                continue;
            }
            System.out.println("i="+i);
        }
    }
}

11.跳转控制语句return

  • 介绍
  • return使用在方法,表示跳出所在的方法,在讲解方法的时候,会详细的介绍,这里我们简单的提一下,注意:如果return写在main方法,退出程序
for(int i=1;i<=5;i++){
    if(i==3){
        System.out.println("韩顺平教育"+i);
        return;//return用在主方法中,直接退出程序,所以输出两个hello world和韩顺平教育
    }
    System.out.println("Hello World");
}
System.out.println("go on");

本章作业

1.编程实现如下功能 某人有100000元,每经过一个路口,需要缴费,规则如下: 1)当现金>50000时,每次交5% 2)当现金<=50000时,每次交1000 编程计算该人可以经过多少次路口,要求:使用while break方法完成。

public class JiaoFei{
    public static void main(String[] args){
        double money = 100000;
        int count = 0;
        while(true){
            if(money>50000){
                money = 0.95*money;
            }else if(money>1000 && money<=50000){
                money -= 1000;
            }else{
                break;
            }
            count = count + 1;
        }
        System.out.println("他可以经过"+count+"次路口");
    }
}

我的答案是63 真实结果应该是62,错误原因是我吧第二个判断条件money>1000写成了money>0; 2.判断一个整数,属于哪个范围:大于0;小于0;等于0

import java.util.Scanner;
public class ZhengShuPanDuan{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int number = myScanner.nextInt();
        if (number > 0){
            System.out.println("大于0");
        }else if(number == 0){
            System.out.println("等于0");
        }else{
            System.out.println("小于0");
        }
    }
}

3.判断一个年份是否为闰年

import java.util.Scanner;
public class RunNian{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int year = myScanner.nextInt();
        if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)){
            System.out.println(year+"年是闰年");
        }else{
            System.out.println(year+"年是平年");
        }
    }
}

4.判断一个整数是否为水仙花数,所谓水仙花数是指一个三位数,其各个位上数字立方和等于其本身,例如:153 = 111+333+555

import java.util.Scanner;
public class ShuiXianHua{
    public static void main(String[] args){
        Scanner myScanner = new Scanner(System.in);
        int num = myScanner.nextInt();
        int ge = num % 10;
        int shi = (int)((num % 100) / 10);
        int bai = (int)(num / 100);
        if (num == ge*ge*ge + shi*shi*shi + bai*bai*bai){
            System.out.println(num+"是水仙花数");
        } else{
            System.out.println(num+"不是水仙花数");
        }
    }
}

5.看看一下代码输出什么?

public class Demo{
    public static void main(String[] args){
        int m = 0,n = 3;
        if(m>0){
            if(n>2)
            System.out.println("ok1");
            else
            System.out.println("ok2");
        }
        }
    }
什么都不输出;

6.输出1-100之间的不能被5整除的数,每5个一行

public class Exercise06{
    public static void main(String[] args){
        int count = 0;
        for(int i = 1;i<=100;i++){
            if(i % 5 != 0){
                System.out.print(i+"\t");//注意,这里不可以用单引号,会报错的
                count += 1;
            }
            if(count % 5 == 0){
                System.out.println();
            }
        }
    }
}

7.输出小写的a-z以及大写的Z-A

public class Exercise07{
    public static void main(String[] args){
        for(char c1 = 'a';c1<='z';c1++){
            System.out.println(c1+" ");
        }
        for(char c1 = 'Z';c1 >= 'A';c1--){
            System.out.println(c1+" ");
        }
    }
}

8.求出1-1/2+1/3-1/4...1/100的和

public class Exercise08{
    public static void main(String[] args){
        double num = 1.;
        for(int i = 2;i<=100;i++){
            if(i%2 == 0){
                num = num-1./i;//注意这个地方不能写成1/i必须写成1./i
            }else{
                num = num + 1./i;
            }
        }
        System.out.println("结果为"+num)
    }
}

我的结果为1.0,正确的结果是0.688错误的原因是是因1/2=0,1/3=0....... 9.求1+(1+2)+(1+2+3)+(1+2+3+4)+...+(1+2+3+...+100)的结果

public class Exercise09{
    public static void main(String[] args){
        int count = 0;
        int count1 = 0;
        for(int i = 1;i<=100;i++){
            count = count + i + count1;
            count1 = count;
        }
        System.out.println("结果为"+count);
    }
}

我的结果为-102,整个逻辑就错了。修改过后如下,结果为171700:

public class Exercise09{
    public static void main(String[] args){
        int sumAll = 0;
        for(int i = 1;i<=100;i++){
            int sumSingle = 0;
            for(int j = 1;j<=i;j++){
                sumSingle = sumSingle + j;
            }
            sumAll += sumSingle;
        }
        System.out.println("结果为"+sumAll);
    }
}

第六章数组,排序和查找

1.数组的介绍

  • 数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。即:数(数据)组(一组)就是一组数据
  • 数组快速入门
//定义一个数组
double[] hens = {3,5,1,3.4,2,50};
//数组遍历
for(int i = 0;i<6;i++){
    System.out.println(hens[i]);
}
//提示:可以通过数组名.length得到数据的大小/长度

2.数组的使用方式

  • 使用方式1-动态初始化
    • 数组的定义 数据类型 数组名[] = new 数据类型[大小] int a[] = new int[5];//创建了一个数组,名字a,存放5个int
    • 数组的引用(使用) 数组名[下标/索引]比如:你要使用a数组的第三个数a[2],数组的下标从0开始。
    • 快速入门案例 循环输入5个成绩,保存到double数组,并输出
  • 使用方法2-动态初始化
    • 先声明数组,再new分配空间。 语法:数据类型 数组名[];也可以 数据类型[] 数组名; int a[];或者 int[] a;
    • 创建数组 语法:数组名=new 数据类型[大小]; a = new int[10];
    • 案例演示
public class Array02{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        //声明并开辟空间
        double[] scores = new double[5];
        //赋值
        for(int i = 0;i<5;i++){
            scores[i] = input.nextDouble();
        }
        //打印
        for(int i = 0;i<5;i++){
            System.out.println(scores[i]);
        }
    }
}

3.数组使用注意事项和细节

  • 数组是多个相同类型数据的组合,实现对这些数据的统一管理
  • 数组中的而元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
  • 数组创建后,如果没有赋值,有默认值int 0,short 0,byte 0,long 0,float 0.0,double 0.0,char \u0000,boolean false,String null
  • 使用数组的步骤1.声明数组并开辟空间 2.给数组的各个元素赋值,3 使用数组
  • 数组的下标是从0开始的。
  • 数组下标必须在指定范围内使用,否则报:下标越界异常,比如int[] arr = new int[5];则有效下标为0-4
  • 数组属于引用类型,数组型数据是对象(object)

4.数组的应用案例

  1. 创建一个char类型德26个元素德数组,分别放置‘A’-‘Z’。使用for循环访问所有元素并打印出来。提示char类型数据运算‘A’+1 -> ‘B’
public class ArrayExercise01{
    public static void main(String[] args){
        char array[] = new char[26];
        int start = 0;
        for(char i = 'A';i<='Z';i++){
            array[start] = i;
            start += 1;
        }
        for(int i = 0;i<26;i++){
            System.out.println(array[i]);
        }
    }
}

2.请求出一个数组int[]的最大值{4,-1,9,10,23},并得到对应的下标。

public class ArrayExercise02{
    public static void main(String[] args){
        int[] array = {4,-1,9,10,23};
        int t = 0;
        int n = 0;
        int i = 0;
        for(;i<5;i++){
            if(array[i]>t){
                t = array[i];
                n = i;
            }
        }
        System.out.println("最大值为"+t+"对应的下标为:"+n);
    }
}

3.求出一个数组的和和平均值

public class ArrayExercise03{
    public static void main(String[] args){
        int[] array = {3,2,5,1,8,2,34};
        double sum = 0.;
        double average = 0.;
        for(int i = 0;i<array.length;i++){
            sum += array[i];
        }
        average = sum/(array.length);
        System.out.println("数组的和为"+sum+"数组的平均值为"+average);
    }
}

5.数组的赋值机制

  1. 基本数据类型赋值,这个值就是具体的数据,而且相互不影响。

int n1 = 2;int n2 = n1;//n2的变化不会影响n1 2. 数组在默认情况下是引用传递,赋的值是地址。 3. 看一个案例,分析数组赋值的内存图(重点)。 int n1 = 10; int n2 = n1; n2 = 90; 此时n1不会变成90,仍然是10. 但是数组就不一样了,是地址拷贝(引用拷贝)看下面例子 int [] arr1 = {1,2,3}; int [] arr2 = arr1;//吧arr1赋给arr2,此时arr2的变化会影响arr1 arr2[0] = 10; //此时arr1[0]也变成了10;

int[] arr1 = {1,2,3};
int[] arr2 = arr1;
  • 值传递和引用传递的区别

6.数组拷贝

编写代码 实现数组拷贝(内容复制)将int[] arr1 = {10,20,30};拷贝到arr2数组,要求数据空间是独立的

int[] arr1 = {10,20,30};
int[] arr2 = arr1;//不能这么干,这样说白了就是让arr2指向arr1,他们的数据空间肯定不是独立的.
//正确的做法
//创建一个新的数组arr2,开辟新的数据空间
//大小arr1.length
int[] arr2 = new int[arr1.length];
//遍历arr1,把每个元素拷贝到arr2对应的元素位置
for(int i = 0;i<arr1.length;i++){
    arr2[i] = arr1[i];
}

7.数组的反转

要求:把数组的元素内容反转 arr{11,22,33,44,55,66}->{66,55,44,33,22,11} //思考

  • 方式1:通过规律反转
  • 方式2:使用逆序赋值方式
//方法1
int[] arr = {11,22,33,44,55,66};
//思路:把arr[0] 和arr[5]进行交换,以此类推。
//一共要交换3次 = arr.length/2
//每次交换时,对应的下标是arr[i]和arr[arr.length-1-i]
for(int = 0;i<arr.length/2;i++){
    int temp = arr[arr.length-1-i];//暂存
    arr[arr.length-1-i] = arr[i];
    arr[i] = temp;
}
System.out.println("====反转后数组====");
for(int i = 0;i<arr.length;i++){
    System.out.println(arr[i] + "t");
}
//方法2
int[] arr1 = {11,22,33,44,55,66};
int len = arr1.length;
int[] arr2 = new int[len];
for(int i = 0;i<len;i++){
    arr2[len-i-1] = arr1[i];
}
System.out.println("=====反转后的数组====");
for(int i = 0;i<len;i++){
    System.out.println(arr2[i] + "\t");
}
//或者方法2也可以这么写
for(int i = len-1,j=0;i>=0;i--,j++){
    arr2[j] = arr[i];
}

8.数组添加

要求:实现动态的给数组添加元素效果,实现对数组扩容。

  1. 原始数组使用静态分配int[] arr = {1,2,3}
  2. 增加的元素,直接放在数组的最后arr = {1,2,3,4} arrNew = {1,2,3,4}
  3. 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
public class ArrayAdd{
    public static void main(String[] args){
        /*
        思路分析
        1.定义初始数组int[] arr = {1,2,3}//下标0-2
        2.定义一个新的数组 int[] arrNew = new int[arr.length+1];
        3.遍历arr数组,依次将arr的元素拷贝到arrNew数组
        4.将4赋值给arrNew最后一个元素。[arrNew.length-1] = 4;
        5.让arr 指向arrNew;arr = arrNew;那么原来的arr数组就被销毁。
        */
        int[] arr = {1,2,3};
        int[] arrNew = new int[arr.length + 1];
        //遍历arr数组,一次将arr的元素拷贝到arrNew数组
        for(int i = 0;i< arr.length;i++){
            arrNew[i] = arr[i];
        }
        //把4赋给arrNew的最后一个元素
        arrNew[arrNew.length - 1] = 4;
        //让arr 指向arrNew;
        arr = arrNew;
        //输出arr看看效果
        System.out.println("======arr扩容后元素情况======");
        for(int i = 0;i< arr.length;i++){
            System.out.println(arr[i] + "\t");
        }
    }
}
//下面的程序是为了实现3功能
import java.util.Scanner;
public class ArrayAdd02{
    public static void main(String[] args){
        int[] arr = {1,2,3};
        Scanner myScanner = new Scanner(System.in);
        while(true){
            System.out.println("是否继续?y/n");
            char ans = myScanner.next().charAt(0);
            if(ans == 'n'){break;}
            System.out.println("请输入要添加的元素");
            int[] arrNew = new int[arr.length + 1];
            //遍历arr数组,一次将arr的元素拷贝进arrNew数组
            for(int i = 0;i<arr.length;i++){
                arrNew[i] = arr[i];
            }
            int num = myScanner.nextInt();
            //把num赋给arrNew最后一个
            arrNew[arrNew.length - 1] = num;
            //让arr指向arrNew;
            arr = arrNew;//原来的arr会被销毁 
            //输出arr看看效果
            System.out.println("=====arr扩容后元素情况=======");
            for(int i = 0;i< arr.length;i++){
                System.out.println(arr[i] + "\t");
            }
        }
    }
}

课后练习题: 要求:有一个数组{1,2,3,4,5}可以将该数组进行缩减,提示用户是否继续缩减,每次缩减最后一个元素,当只剩下最后一个元素时提示:不能再缩减。

import java.util.Scanner;
public class ArrayReduce{
    public static void main(String[] args){
        int[] myArray = {1,2,3,4,5};
        Scanner myScanner = new Scanner(System.in);
        while(true){
            int[] myNewArray = new int[myArray.length-1];
            //提示用户是否进行缩减
            System.out.println("是否进行缩减操作?y/n");
            char ans = myScanner.next().charAt(0);
            if(ans == 'n'){System.out.println("程序退出");break;}
            if(myArray.length == 1){
                System.out.println("元素只剩一个,不能缩减");
                break;
            }
            for(int i = 0; i<myNewArray.length;i++){
                myNewArray[i] = myArray[i];
            }
            myArray = myNewArray;
            //输出myArray看看效果
            for(int i = 0;i<myArray.length;i++){
                System.out.print(myArray[i] + "\t");
            }
        }
    }
}

9.排序的介绍

排序是将一群数据,依照指定的顺序进行排列的过程 排序的分类

  1. 内部排序 指将需要处理的所有数据都加载导内部的存储器种进行排序。包括(交换式排序法,选择式排序法和插入式排序法);
  2. 外部排序法: 数据量过大,无法全部加载导内存中,需要借助外部存储进行排序,包括(合并排序法和直接合并排序法)

10.冒泡排序

冒泡排序的基本思想时:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使得值较大的元素逐渐从前移向后部,就像水底气泡一样向上冒。

  • 冒泡排序案例

将五个无序:24,69,80,57,13使用冒泡排序法从小到大排列。

  • 冒泡排序代码实现
public class BubbleSort{
    //编写一个main方法
    public static void main(String[] args){
        //化繁为简,先死后活
        /*
        数组[24,69,80,57,13]
        第一轮排序:目标把最大数放在最后
        第一次比较[24,69,80,57,13]
        第二次比较[24,69,80,57,13]
        第三次比较[24,69,57,80,13]
        第四次比较[24,69,57,13,80]
        */
        int[] arr = {24,69,80,57,13};
        int temp = 0;
        for(int i = 0;i<arr.length-1;i++){
        for(int j = 0;j<arr.length-i;j++){//4次比较
            //如果前面的数>后面的数,就交换
        }
        if(arr[j] > arr[j+1]){
            temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
    System.out.println("===第"+(i+1)+"轮===");
    for(int j = 0;j< arr.length;j++){
        System.out.println(arr[j]+"\t");
    }
}
}

11.查找

  • 介绍

在Java中,我们常用的查找有两种:

  1. 顺序查找
  2. 二分查找

案例演示:

  1. 有一个数列,白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:从键盘中任意输入一个名称,判断数列中是否包含此名称(顺序查找)要求:如果找到了,就提示找到,并给出下标值。
  2. 请对一个有序数组进行二分查找,{1,8,10,89,1000,1234},输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示”没有这个数“。
public class SeqSearch{
    public static void main(String[] args){
        String[] names = {"白眉鹰王","金毛狮王","紫衫龙王","青翼蝠王"};
        //遍历数组,注意比较,如果有,则提示信息,并退出
        //这里老师给大家一个编程思想/技巧,一个经典的方法
        int index = -1;
        for(int i = 0;i< names.length;i++){
            //比较字符串equals,如果找到名字就是当前元素
            if(findName.equals(names[i])){
                System.out.println("恭喜你找到"+findName);
                System.out.println("下标为"+i);
                //把i保存在index中
                index = i;
                break;
            }
        }
        if(index == -1){
            //没有找到
            System.out.println("没有找到");
        }
    }
}

12.二维数组的使用

请用二维数组输出如下图形 000000 001000 020300 000000

//从形式上看int[][]
//可以这样理解,原来的一维数组的每个元素是一维数组
int[][] arr = {{0,0,0,0,0,0},
               {0,0,1,0,0,0},
               {0,2,0,3,0,0},
               {0,0,0,0,0,0}};
//输出二维图形
for(int i = 0;i< arr.length;i++){
    //遍历二维数组的每个元素
    //遍历二维数组的每个元素
    for(int j = 0;j<arr[i].length;j++){
        System.out.println(arr[i][j] + " ");
    }
    System.out.println();//换行
}
  • 使用方法1:动态初始化
    • 语法:类型[][]数组名 = new 类型[大小][大小]
    • 比如:int a[][] = new int[2][3]
    • 使用演示
    • 二维数组在内存中的存在形式

  • 使用方法2:动态初始化

    • 先声明:类型 数组名[][];
    • 再定义(开辟空间)数组名 = new 类型[大小][大小]
    • 赋值(有默认值,比如int 类型的就是0)
    • 使用演示
  • 使用方法3:动态初始化-列数不确定

    • 看一个需求:动态创建下面的二维数组,并输出。
    • 完成该案例
    • 画出执行分析示意图;
public class TwoDimensionalArray03{
    //编写一个main方法
    public static void main(String[] args){
        /*
        看一个需求:动态创建下面的二维数组,并输出
        i = 0:1
        i = 1:2 2
        i = 2:3 3 3
        一个有三个一维数组,每个一维数组的元素是不一样的
        */
        //创建一个二维数组,一个有3个一维数组,但是每一个一维数组还没有开数据空间。
        int[][] arr = new int[3][];//列数不确定就不写。
        for(int i = 0;i<arr.length;i++){
            //遍历arr每一个一维数组
            //如果没有给一维数组new 那么arr[i]就是null
            arr[i] = new int[i+1];
            //遍历一维数组,并给一维数组的每个元素赋值
            for(int j = 0;j< arr[i].length;j++){
                arr[i][j] = i + 1;
            }
        }
        //遍历arr输出
        for(int i = 0;i< arr.length;i++){
            for(int j = 0;j< arr[i].length;j++){
                System.out.print(arr[i][j] + " ");
            }
        }
    }
}
  • 使用方式4:静态初始化
    • 定义: 类型 数组名[][] = {{值1,值2..},{值1,值2..},{值1,值2...}}
    • 使用即可[固定方式访问]
    • 比如:int[][] arr = {{1,1,1},{8,8,9},{100}};

13.二维数组的遍历

案例:int arr[][] = {{4,6},{1,4,5,7},{-2}};遍历该二维数组,并求和

public class TwoDimensionalArray05{
    //编写main方法
    public static void main(String[] args){
        int count = 0;
        int arr[][] = {{4,6},{1,4,5,7},{-2}};
        for(int i = 0;i<arr.length;i++){
            for(int j = 0;j< arr[i].length;j++){
                count = count + arr[i][j];
            }
        }
        System.out.println("该二维数组的和为"+count);
    }
}

案例:使用二维数组打印一个10行的杨辉三角 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 规律:

  1. 第一行有1个元素,第n行有n个元素
  2. 第一行的第一个元素和最后一个元素都是1
  3. 从第三行开始,对于非第一个元素和最后一个元素的元素值a[i][j] arr[i][j] = arr[i-1][j] + arr[i-1][j-1];//必须找到这个规律
public class YangHui{
    public static void main(String[] args){
        int[][] arr = new int[10][];//开辟空间
        for(int i = 0;i<arr.length;i++){
            arr[i] = new int[i+1];//开辟内层空间
            for(int j = 0;j< arr[i].length;j++){
                if(j == 0 || j == arr[i].length - 1){//每一行第一个元素和最后一个元素都是1
                    arr[i][j] = 1;
                }else{
                    arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
                }
            }
        }
        //输出打印看一下
        for(int i = 0;i<arr.length;i++){
            for(int j = 0;j<arr[i].length;j++){
                System.out.print(arr[i][j] + "\t");
            }
        }
        System.out.println();
    }
}

14.二维数组使用细节和注意事项

  • 一维数组的声明方式有: int[] x或者int x[]
  • 二维数组的声明方式有: int[][] y或者 int[] y[] 或者int y[][]
  • 三维数组实际上是由多个一维数组组成的,他的各个一维数组的长度可以相同也可以不同。比如:map[][] = {{1,2},{3,4,5}}
  • 由map[0]是一个含有两个元素的一维数组,map[1]是一个含有三个元素的一维数组构成,我们也成为列数不等的二维数组

本章作业

第一题我选B,D 第二题我觉得答案是blue 第三题输出1 3 5 7 第四题

import java.util.Scanner;
public class Homework05{
    public static void main(String[] args){
        /*
        已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序,比如:[10,12,45,90],添加23后数组为[10,12,23,45,90]
        */
        //这里我首先用的是冒泡排序做法。
        int[] arr = {10,12,45,90,100,110,112};
        int[] arrNew = new int[arr.length+1];
        int temp = 0;
        System.out.println("请输入一个元素");
        Scanner myScanner = new Scanner(System.in);
        int num = myScanner.nextInt();
        arrNew[0] = num;
        for(int i = 0;i<arr.length;i++){
            arrNew[i+1] = arr[i];
        }
        arr = arrNew;
        for(int j = 0;j< arr.length-1;j++){
            if(arr[j]>arr[j+1]){
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
        System.out.println("添加后数组值如下:");
        for(int i = 0;i < arr.length;i++){
            System.out.print(arr[i]+"\t");
        }
    }
}

根据韩老师的提示,换一个做法

import java.util.Scanner;
public class Homework05{
    public static void main(String[] args){
        /*主要思路
        1.先确定添加数应该插入到那个索引?
        2.然后扩容
        */
        //定义原始数组
        int[] arr = {10,12,45,98,100,110,112};
        int[] arrNew = new int[arr.length+1];//定义新数组
        System.out.println("请输入一个元素");
        Scanner myScanner = new Scanner(System.in);
        int insertNum = myScanner.nextInt();
        int index = -1;//index就是要插入的位置
        //遍历arr数组,如果发现insertNum<=arr[i]说明i就是要插入的位置
        //使用index保留index=i
        for(int i = 0;i<arr.length;i++){
            if(insertNum<=arr[i]){
                index = i;
                break;//找到位置后退出
            }
        }
        //判断index的值
        if(index == -1){//说明还没有找到位置
            index = arr.length;
        }
        //下面将arr的元素拷贝到arrNew并且跳过index位置
        for(int i = 0,j = 0;i<arrNew.length;i++){
            if(index != i){
                arrNew[i] = arr[j];
                j++;
            }
            else{
                arrNew[i] = insertNum;
            }
            // if(index == -1){
            //     arrNew[arrNew.length-1] = insertNum;
            // }
        }
        //让arr指向arrNew
        arr = arrNew;
        //打印扩容后的数组
        for(int i = 0; i< arrNew.length;i++){
            System.out.print(arrNew[i] + "\t");
        }
    }
}

5.随机生成10个整数(1-100)保存导数组,并倒序打印以及求平均值,求最大值和最大值的下标,并查找里面是否有8

public class Homework06{
    public static void main(String[] args){
        int[] arr = new int[10];
        int max = 0;//定义最大值和最小值和和,这里初始化为arr[0]最好
        int min = 100;
        int maxIndex = 0;//定义最大值最小值的下标
        int minIndex = 0;
        double sum = 0.;//这里初始化为arr[0]最好
        int temp = -1;
        double average = 0.;
        for(int i = 0;i<10;i++){//生成数组
            int num = (int)(Math.random()*100)+1;
            arr[i] = num;
        }//顺序打印
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr[i]+"\t");
        }
        System.out.println();
        for(int i = 0;i< arr.length;i++){//打印信息
            System.out.print(arr[arr.length-i-1]+"\t");
            sum += arr[i];
            if(arr[i]>=max){
                max = arr[i];
                maxIndex = i;
            }
            if(arr[i]<=min){
                min = arr[i];
                minIndex = i;
            }
            //检查生成的数组里面是否含有8;
            if(arr[i] == 8){
                temp = 0;
            }
        }
        System.out.println();
        average = sum/arr.length;
        if(temp == -1){
            System.out.println("这里面不含有8");
        }else{
            System.out.println("里面含有8");
        }
        System.out.println("平均值为:"+average+"最大值为"+max+"最大值下标为"+maxIndex+"最小值为"+min+"最小值的下标为"+minIndex);
    }
}

第六题我认为答案为:aa zz 韩韩 cc 7.写出冒泡排序的代码

import java.util.Scanner;
public class Homework07{
    public static void main(String[] args){
        int temp = 0;
        int count = 0;
        int[] arr = {1,4,3,2};
        Scanner myScanner = new Scanner(System.in);
        while(true){//一直问是否继续添加元素
            System.out.println("是否添加?y/n");
            char choice = myScanner.next().charAt(0);
            if(choice == 'n'){
                System.out.println("退出添加");
                break;
            }
            System.out.println("请输入你要添加的元素");
            int num = myScanner.nextInt();
            int[] arrNew = new int[arr.length+1];
            for(int i = 0;i < arr.length;i++){
                arrNew[i] = arr[i];
            }
            arrNew[arrNew.length-1] = num;
            arr = arrNew;
        }
        //冒泡排序
        for(int i = 0;i< arr.length-1;i++){
            for(int j = 0 ;j< arr.length-1-i;j++){
                if(arr[j]>arr[j+1]){
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        //输出排序后的结果
        for(int i = 0;i< arr.length;i++){
            System.out.print(arr[i]+"\t");
        }
    }
}

第七章面向对象编程基础部分

类与对象的引出

  • 看一个养猫问题 //使用面向对象的方式来解决养猫问题
public class Cat{
    public static void main(String[] args){
        //使用oop面向对象来解决
        //实例化一只猫(创建一只猫对象)
        //1.new Cat()创建一只猫
        //2.Cat cat1 = new Cat();把创建的猫赋给cat1
        Cat cat1 = new Cat();
        cat1.name = "小白";
        cat1.age = 3;
        cat1.color = "white"
        //创建第二只猫
        Cat cat2 = new Cat();d
        cat2.name = "小花";
        cat2.age = 100;
        cat2.color = "black";
        //访问对象属性
        System.out.println("第一只猫的信息"+cat1.name+" "+cat1.age + " "+cat1.color);
    }
}
//定义一个猫类,(自定义的数据类型)
class Cat{
    //属性
    String name;//名字
    int age;//年龄
    String color;//颜色
    //行为 
}

张老太养了两只猫,一只名字叫做小白,今年3岁,白色,还有一只叫做小花,今年100岁,花色。请编写一个程序, 当用户输入小猫名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名字错误,则显示张老太没有这只猫。 类喝对象的区别和联系

  1. 类是抽象的,概念的,代表一类事物,比如猫类,人类,即他是数据类型
  2. 对象是具体的,实际的,代表一个具体食物,即是实例
  3. 类是对象的模板,对象是类的一个个体,对应一个实例。

对象内存布局

对象在内存中存在形式

Cat cat = new Cat();
//cat是对象名,(对象引用)相当于人的名字
//new Cat()创建的对象空间(数据)才是真正的对象。相当于真正的人。
cat.name = "小白";
cat.age = 12;
cat.color = "red";

属性的概念

  • 属性/成员变量
  1. 从概念或叫法上看,成员变量=属性=field(字段)(即成员变量是用来表示属性的,授课中 统一叫属性)
  2. 属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)比如我我们前面定义猫类的int age就是属性
  • 注意事项和细节
  1. 属性的定义语法同变量,实例:访问修饰符 属性类型 属性名;
    1. 访问修饰符:控制属性的访问范围,有四种访问修饰符:public proctected ,默认,private
  2. 属性的定义类型可以为任意类型,包含基本类型和引用类型
  3. 属性如果不赋值,有默认值,规则和数组一样。

创建对象访问属性

  • 如何创建对象
  1. 先声明再创建 Cat cat;//声明对象cat cat = new Cat();//创建
  2. 直接创建 Cat cat = new Cat();

类和对象的内存分配机制(重要)

看一个思考题 我们定义一个人类(Person)包括名字和年龄 看看下面一段代码

Person p1 = new Person();
p1.age = 10;
p1.name = "小明";
Person p2 = p1;//p1赋给了p2,让p2指向p1
System.out.println(p2.age);

请问p2.age究竟是多少?并画出内存图:

对象创建过程

  • 类和对象的内存分配机制
    • Java内存的结构分析
      1. 栈:一般存放基本数据类型(局部变量)
      2. 堆:存放对象(Cat cat,数组等)
      3. 方法区:常量池(常量,比如字符串),类加载信息
      4. 示意图[Cat(name,age,price)] *Java创建对象的流程简单分析 Person p = new Person(); p.name = "jack"; p.age = 10
    1. 先加载Person类信息(属性和方法信息,只会加载一次)
    2. 在堆中分配空间,进行默认初始化(看规则),把地址赋给p,p就指向对象
    3. 把地址赋给p,p就指向对象
    4. 进行指定初始化,比如p.name = "jack" p.age = 10

对象机制练习

看一个习题,并分析画出内存布局图

Person a = new Person();
a.age = 10;
a.name = "小马";
Person b;
b = a;
System.out.println(b.name);
b.age = 200;
b = null;
System.out.println(a.age);
System.out.println(b.age);

成员方法

  • 基本结束 在某些情况下,我们需要定义成员方法(简称方法)。比如人类:除了有一些属性外(年龄,姓名。。),我们人类还有一些行为比如:可以说话,跑步。。通过学习,还可以做算术题。这时候就要用成员方法才能完成。
  • 成员方法快速入门
    1. 添加speak成员方法,输出,我是一只好人
    2. 添加cal01 成员方法,可以计算从1+..+1000的结果
    3. 添加cal02成员方法,该方法可以接受一个数n,计算从1+..+n的结果
    4. 添加getSum成员方法,可以计算两个数的和
  • 方法的调用机制原理(重要!-示意图) 提示:画出程序执行过程[cal02]+说明
public class Method01{
    public static void main(String[] args){
        //方法使用
        //1.方法写好后,如果不去调用(使用)就不会输出
        //2.先创建对象,然后调用方法即可
        Person p1 = new Person();
        p1.speak();//调用方法
        p1.cal01();//调用cal01方法
        p1.cal02(5);//调用cal02方法,同时给n = 5
        p1.cal02(10);//调用cal02方法,同时给n = 10
        int returnRes = p1.getSum(10,20);//调用getSum方法,同时赋值,用returnRes接收
    }
}
class Person{
    String name;
    int age;
    //方法(成员方法)
    //添加speak 成员方法,输出“我是一个好人”
    //1.public 表示方法是公开的
    //2.void :代表方法是没有返回值
    //3.speak():speak是方法名,()形参列表
    //4.{}方法体,可以写我们执行的代码
    public void speak(){
        System.out.println("我是一个好人");
    }
    //添加cal01 成员方法,可以计算从1+..+1000的结果
    public void cal01(){
        //循环完成
        int res = 0;
        for(int i = 1;i<= 1000;i++){
            res += i;
        }
        System.out.println("计算结果="+res);
    }
    //添加cal02成员方法,该方法可以接受一个数n,计算1+..+n的结果
    //1.(int n)形参列表 表示当前有一个形参,可以接受用户的输入
    public void cal02(int n){
        //循环完成
        int res = 0;
        for(int i = 1;i<= n;i++){
            res += i;
        }
        System.out.println("cal02方法 计算结果="+res);
    }
    //添加getSum成员方法,可以计算两个数的和
    //public表示方法是公开的
    //int:表示方法在执行后,返回一个值
    //getSum 方法名
    //(int num1,int num2)形参列表,2个形参,可以接受用户传入的两个数
    //return res;表示把res值返回给
    public int getSum(int num1,int num2){
        int res = num1 + num2;
        return res;
    }
}

方法的调用机制

方法调用小节

  1. 当程序执行方法时,就会开辟一个独立空间(栈空间)
  2. 当方法执行完毕,或者执行到return语句,就会返回
  3. 返回到调用方法的地方,开辟的独立空间被销毁。
  4. 返回后,继续执行方法后面的代码
  5. 当主方法main执行完毕,整个程序退出

成员方法的必要性

为什么需要成员方法?看一个需求 遍历一个数组,输出数组的各个元素值。

public class Method02{
    //编写一个main方法
    public static void main(string[] args){
        //遍历一个数组,输出数组的各个元素值
        int[][] map = {{0,0,1},{1,1,1},{1,1,3}};
        //遍历map数组
        //传统的解决方法就是直接遍历,但是代码复用性差,用起来不方便。
        for(int i = 0;i< map.length;i++){
            for(int j = 0;j<map[i].length;i++){
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
        //另一个思路:定义一个类MyTools,然后写一个成员方法,调用方法实现,看看效果如何。
        //成员方法的好处:代码的复用性更高,可以将实现的细节封装起来,然后供其他用户来调用即可
        MyTools tool = new MyTools();
        tool.printArray(map);
    }
}
//把输出的功能,写到一个类的方法种,然后调用该方法即可
class MyTools{
    //方法,接收一个二维数组
    public void printArray(int[][] map){
        //打印传入的map数组
        for(int i = 0;i< map.length;i++){
            for(int j = 0;j<map[i].length;i++){
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
    }
}

成员方法的定义

public 返回数据类型 方法名(参数列表){//方法体 语句; return 返回值; }

  1. 参数列表:表示成员方法输入cal(int n)
  2. 数据类型(返回类型):表示成员方法输出,void表示没有返回值
  3. 方法主体:表示为了实现某一功能代码块
  4. return语句不是必须的。
  5. 结合前面的示意图来理解

方法使用的细节

  • 修饰符(作用是控制方法使用的范围)可选,有4种,如果不写,就是默认访问。具体在后面说
  • 返回类型
    1. 一个方法最多有一个返回值,(思考,如何返回多个结果) 处理方法是返回一个数组,例如
    //返回两个整数的和与差
    public class Test{
     public static void main(String[] args){
         AA a = new AA();
         int[] res = a.getSumAndSub(1,4);
     }
    }
    class AA{
     //将和,差返回值保存到数组中
     public int[] getSumAndSub(int n1,int n2){
         int[] resArr = new int[2];//创建一个数组
         resArr[0] = n1 + n2;
         resArr[1] = n1 - n2;
         return resArr;
     }
    }
    
    1. 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
    2. 如果方法要求有返回数据类型,则方法体种最后执行语句必须为return值;而且要求返回值类型必须和return的值类型一致或兼容
    3. 如果方法是void,则方法体种可以没有return语句,或者只写return;
      1. 方法名 遵循驼峰命名法,最好见名知意,表达出该功能的意思即可,比如得到两个数的和getSum开发中按照规范
  • 形参列表
    1. 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开,如getSum(int n1,int n2)
    2. 参数类型可以为任意类型,包含基本类型和引用类型,如printArr(int[][] map)
    3. 调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
    4. 方法定义时的参数称为形式参数,简称形参;方法调用时的参数称为实际参数,简称实参,实参和形参的类型一定要兼容,个数,顺序必须一致
  • 方法体
    1. 里面写完成功能的具体的语句,可以为输入,输出,变量,运算,分支,循环,方法调用,但里面不能再定义方法。即:方法不能嵌套定义
  • 方法调用细节说明
    1. 同一个类中的方法调用:直接调用即可,比如print(参数) 案例演示:A类 sayOk 调用 print()
    public class MethodDetail02{
        public static void main(String[] args){
    
        }
    }
    class A{
        //同一个类的方法调用:直接调用即可
        public void print(int n){
            System.out.println("print()方法被调用 n="+n);
        }
        public void sayOk(){//sayOk调用print(直接调用)
            print(10);
        }
    }
    
    1. 跨类中的方法A类调用B类方法:需要通过对象名调用。比如 对象名.方法名(参数) 案例演示:B类 sayHello 调用 print()
    public class MethodDetail03{
     public static void main(String[] args){
    
     }
    }
    class A{
     //跨类中的方法A类调用B类方法:需要通过对象名调用
     public void m1(){
         //创建B对象
         B b = new B();
         b.hi();
     }
    }
    class B{
     public void hi(){
         System.out.println("B类中的hi()被执行");
     }
    }
    
    1. 特别说明一下:跨类的方法调用和方法的访问修饰符相关

方法练习题

  1. 编写一个类AA,有一个方法,判断一个数是奇数还是偶数,返回boolean
public class MethodExercise01{
    public static void main(String[] args){
        AA a = new NN();
        boolean b = a.odd(1);
    }
}
//编写类AA,有一个方法:判断一个数奇偶性
class AA{
    public boolean odd(int n){

        //可以用三元运算符
        return num % 2 != 0 ? true:false;
        //也可以直接这样写
        return num % 2 != 0;
    }
}

2.根据行、列、字符打印对应行数和列数的字符,比如:行:4,列:4,字符#,则打印相应的效果

public class MethodExercise{
    public static void main(String[] args){
        AA a = new AA();
        a.printChar(4,4);
    }
}
class AA{ 
    public void printChar(int row ,int column){
        for(int i = 0; i< row;i++){
            for(int j = 0; j < column;j++){
                System.out.print("#");
            }
            System.out.println();
        }
    }
}

方法传参机制

  • 基本数据类型的传参机制
    1. 看一个案例,看输出是什么。
public class Test{
    public static void main(String[] args){
        int a = 10;
        int b = 20;
        //创建AA对象
        AA swap  = new AA();
        swap.swap(a,b);//调用swap
        System.out.println("a=" + a + "b=" + b);//a=10 b=20,这里面输出的a,b都是主栈的a,b
    }
}
class AA {
    public void swap(int a,int b){
        System.out.println("\na和b交换的值\na="+a + "\tb=" + b);//a=10 b=20,这里面的a,b都是swap栈里面的a,b
        //完成a和b的交换
        int tmp = a;
        a = b;
        b = tmp;
        System.out.println("\na和b交换后的值\na=" + a+"\tb="+b);//a=20 b=10 这里面的a,b都是swap栈里面的a,b
    }
}

结论: 对于基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参!

  • 引用数据类型的传参机制
    1. 看一个案例 B类中编写一个方法test100,可以接受一个数组,在方法中修改该数组,看看原来的数组是否变换? B类中编写一个方法test200,可以接受一个Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变换?(有变化,因为对象也是引用类型)
public class Method{
    public static void main(String[] args){
        //测试
        B b = new B();
        int[] arr = {1,2,3};
        b.test100(arr);//调用方法,arr传递的是地址!!!!!!
        System.out.println("tes的arr数组");
        //遍历数组
        System.out.println("main的数组");
            for(int i = 0;i< arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        //测试
        Person p = new Person();
        p.name = "jack"
        p.age = 20;
        b.test200(p);
        System.out.println("main的p.age="+p.age);//10000
    }
}
class B{
    //B类中编写一个方法test100,
    //可以接受一个数组,在方法中修改数组,看看原数组是否变化
    public void test100(int[] arr){
        arr[0] = 200;
        //遍历数组
        System.out.println("test100的arr数组");
        for(int i = 0;i< arr.length;i++){
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}
class Person{
    String name;
    int age;
}
class B{
    public void test200(Person p){
        p.age = 10000;//修改对象属性
    }
}

数组是引用类型,引用类型传递时传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参! 输出结果,发现main栈的数组已经被改变了(形参影响实参),因为main栈和test100栈的arr都指向同一个地址,(arr传递是地址) test100的arr数组 200 2 3 main的arr数组 200 2 3 如图,在test200中将p置空,主栈中p.age输出什么? 答案仍然是输出10000,而不是异常,原因是,test200中p置空只是让test200里面的p指向空指针 对主栈中的p没有影响 如图,在test200里面重新new一个对象p,那么主栈中输出如何? 答案是,仍然对主栈没有影响,因为test200栈中p指向了新开的一个对象

成员方法传参机制

  • 成员方法返回类型是引用类型应用案例
  1. 编写类MyTools类,编写一个方法可以打印二维数组的数据
  2. 编写一个方法copyPerson可以复制一个Person对象,返回复制的对象,克隆对象,注意要求得到的新对象和原来的对象是两个独立的对象,只是他们的属性相同。
public class Method{
    public static void main(String[] args){
        Person p1 = new Person();
        p1.name = "milan";
        p1.age = 100;
        //创建一个对象
        MyTools tools = new MyTools();
        Person p2 = tools.copyPerson(p);
        //p1和p2是Person对象,但是是两个独立的对象,属性相同
        System.out.println(p1 == p2);
    }
}
class Person{
    String name;
    int age;
}
class MyTools{
    //编写一个方法copyPerson可以复制一个Person对象,返回复制的对象,克隆对象,注意要求得到的
    //新对象和原来的对象是两个独立的对象,只是他们的属性相同。
    //思路:
    //方法的返回类型Person
    //方法的名字copyPerson
    //方法的形参Person p
    //方法体,创建一个新对象,复制属性,返回即可
    public Person copyPerson(Person p){
        //创建一个新对象
        Peron p2 = new Person();
        p2.name = p.name;
        p2.age = p.age;
        return p2;
    }
}

方法递归调用

  • 基本介绍 简单来说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂问题,同时可以让代码变得简洁
  • 递归举例
  1. 打印问题
  2. 阶乘问题
//输出什么
public void test(int n){
    if(n > 2){
        test(n -1);
    }
    System.out.println("n=" + n);
}
//阶乘
public int factorial(int n){
    if(n == 1){
        return 1;
    }else{
        return factorial(n-1)*n;
    }
}

本文章使用limfx的vscode插件快速发布