0%

JavaSE初阶

  • JavaSE简介
  • 数据类型
  • 运算符
  • 流程控制
  • 方法的定义、调用、重载
  • 数组

JavaSE简介

美国SUN(Stanford University Network)公司,Java的发明人 James Gosling

  • JavaSE(Java Standard Edition):标准版,定位在个人计算机上的应用
    • 坦克大战、超级马里奥、打飞机、五子棋等
  • JavaEE(Java Enterprise Edition):企业版,定位在服务器端的应用
    • 做购物网站、框架等
  • JavaME(Java Micro Edition):微型版,定位在消费性电子产品的应用上
    • 老手机小游戏

Java的特性及优势

  • 跨平台/可移植性
  • 安全性
  • 面向对象
  • 简单性
  • 高性能
  • 分布式
  • 多线程
  • 健壮性

注意:SUN公司已经被oracle公司收购,目前每半年更新一次java的版本。但是,企业中的主流仍然以7和8为主。对于初学者,应该以企业主流应用版本为核心进行学习,没有必须在此处追求最新版本。

不同版本JDK说明
  • JDK Version 1.1
    • 于1997-02-19发行。
    • 引入的新特性包括:
    • 引入JDBC(Java Database Connectivity);
    • 支持内部类;
    • 引入Java Bean;
    • 引入RMI(Remote Method Invocation);
    • 引入反射(仅用于内省)。
  • J2SE Version 1.2
    • 开发代号为Playground(操场),于1998-12-08发行。
    • 引入的新特性包括:
    • 引入集合(Collection)框架;
    • 对字符串常量做内存映射;
    • 引入JIT(Just In Time)编译器;
    • 引入对打包的Java文件进行数字签名;
    • 引入控制授权访问系统资源的策略工具;
    • 引入JFC(Java Foundation Classes),包括Swing 1.0、拖放和Java 2D类库;
    • 引入Java 插件;
    • 在JDBC中引入可滚动结果集、BLOB、CLOB、批量更新和用户自定义类型;
    • 在Applet中添加声音支持。
  • J2SE Version 1.3
    • 开发代号为Kestrel(红隼),于2000-05-08发行。
    • 引入的新特性包括:
    • 引入Java Sound API;
    • jar文件索引;
    • 对Java的各个方面都做了大量优化和增强。
  • J2SE Version 1.4
    • 开发代号为Merlin(隼),于2004-02-06发行(首次在JCP下发行)。
    • 引入的新特性包括:
    • XML处理;
    • Java打印服务;
    • 引入Logging API;
    • 引入Java Web Start;
    • 引入JDBC 3.0 API;
    • 引入断言;
    • 引入Preferences API;
    • 引入链式异常处理;
    • 支持IPv6;
    • 支持正则表达式;
    • 引入Image I/O slot machine API。
  • Java Version SE 5.0
    • 开发代号为Tiger(老虎),于2004-09-30发行。
    • 引入的新特性包括:
    • 引入泛型;
    • 增强循环,可以使用迭代方式;
    • 自动装箱与自动拆箱;
    • 类型安全的枚举;
    • 可变参数;
    • 静态引入;
    • 元数据(注解);
    • 引入Instrumentation。
  • Java Version SE 6
    • 开发代号为Mustang(野马),于2006-12-11发行。
    • 引入的新特性包括:
    • 支持脚本语言;
    • 引入JDBC 4.0 API;
    • 引入Java Compiler API;
    • 可插拔注解;
    • 增加对Native PKI(Public Key Infrastructure)、Java GSS(Generic Security Service)、Kerberos和LDAP(Lightweight Directory Access Protocol)的支持;
    • 继承Web Services;
    • 做了很多优化。
  • Java Version SE 7
    • 开发代号是Dolphin(海豚),于2011-07-28发行。
    • 引入的新特性包括:
    • switch语句块中允许以字符串作为分支条件;
    • 在创建泛型对象时应用类型推断;
    • 在一个语句块中捕获多种异常;
    • 支持动态语言;
    • 支持try-with-resources;
    • 引入Java NIO.2开发包;
    • 数值类型可以用2进制字符串表示,并且可以在字符串表示中添加下划线;
    • 钻石型语法;
    • null值的自动处理。
  • Java Version SE 8
    • 开发代号是Spider(蜘蛛),于2014-03-18发行。
    • 支持 lambda支持;
    • 增强日期与时间API的功能;
    • 对垃圾回收的性能也进行了改进;
    • 并且移除了permgen区。
    • Lambdas表达式与Functional接口
    • 接口的默认与静态方法
    • 方法引用
    • 重复注解
    • 更好的类型推测机制
    • 扩展注解的支持

核心机制

垃圾收集机制

垃圾收集的目的在除不再使用的对象,当对象建立的时候垃圾收集期,就开始监控对象的动态情况,垃圾收集主要是对内存的释放。创建对象的时候申请一个空间

  1. 不再使用的内存空间应回收—》垃圾收集;
  2. Java消除了程序员回收无用内存空间的职责;提供一种系统级线程跟踪存储空间的分配情况。在JVM的空闲时,检查并释放可被释放的存储器空间;相比c++,开发人员负责要自己收回无用内存。
  3. 垃圾收集在Java程序运行过程中自动进行,程序员无法精确控制和干预;
  4. GC的自动回收,提高了内存空间的利用效率,也提高了编程人员的效率,很大程度上减少了因为没有释放空间而导致的内存泄露。

后续:更高级问题,待研究

  1. 垃圾收集器有几种
  2. 垃圾收集器底层原理剖析
  3. 垃圾收集器算法,优化

跨平台原理(重点)

JAVA跨平台原理

C语言的跨平台解释

JVM(Java Virtual Machine)就是一个虚拟的用于执行bytecode字节码的”虚拟计算机”。他也定义了指令集、寄存器集、结构栈、垃圾收集堆、内存区域。JVM负责将Java字节码解释运行,边解释边运行,这样,速度就会受到一定的影响。

不同的操作系统有不同的虚拟机。Java 虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,随处运行”。 Java虚拟机是实现跨平台的核心机制

我们说的语言跨平台是编译后的文件跨平台,而不是源程序跨平台。
接下来我们再比较下两种方式的差异:第一,C语言是编译执行的,编译器与平台相关,编译生成的可执行文件与平台相关;第二,Java是解释执行的,编译为中间码的编译器与平台无关,编译生成的中间码也与平台无关(一次编译,到处运行),中间码再由解释器解释执行,解释器是与平台相关的,也就是不同的平台需要不同的解释器

常用DOS命令
  • Microsoft公司推出的操作系统。(在windows之前的操作系统)
  • DOS是英文”Disk Operating System”的缩写,其中文含意是”磁盘操作系统”.
  • DOS是单用户、单任务的操作系统.(只能执行一个任务)
  • windows中,通过鼠标菜单等来操作系统,而在dos操作系统中,要通过dos命令来操作系统。
  • DOS操作系统的命令,是一种面向磁盘的操作命令,不区分大小写。
  • windows给我们保留了类似dos系统的操作界面,可以直接操作磁盘!
  • dos 也是一种操作系统,是在windows出现以前用的,后来windows出来后基本没人用了,但是当windows崩溃的时候,还是要的dos方式解决
  • 它是一种纯命令方式,cmd其实就是在windows状态下进入dos方式。

控制命令台:win+r--->cmd

具体dos命令(不区分大小写)

  1. 切换盘符: c: d: e:
  2. 显示详细信息:dir
  3. 改变当前目录:cd youdirpushd youdir
  4. 代表当前目录:.
  5. 代表上一层目录:..
  6. 清屏:cls
  7. 切换历史命令:上下箭头
  8. 补全命令: tab按键
  9. 创建目录:md a
  10. 删除目录:rd a
  11. 复制文件命令:copy old.txt a/new.txt
  12. 删除文件:del del后面如果接的是文件夹/目录,那么删除的就是这个文件夹下的文件,而不是文件夹
JDK环境
  • 下载 JDK
  • 安装JDK:一直下一步就行
  • 卸载JDK:控制面板卸载
  • 验证安装:① 去安装目录下看一眼;② 通过控制命令台查看;③ 通过控制面板查看

  • JDK: Java Development kit —->编写Java程序的程序员使用的软件
  • JRE : Java Runtime Enviroment —-》运行Java程序的用户使用的软件

添加环境变量

Notepad、IDEA安装

这里使用 IDEA ……

编写代码
1
2
3
4
5
6
7
8
9
public class Test{
public static void main(String[] args){
HelloWord();
}
public static void HelloWord(){
String a = "hi 这是\n一段\tJava程序。。。";
System.out.println(a);
}
}

编译、解析/翻译/执行

1
2
javac Test.java
java Test

扩展

1
2
3
// 反汇编过程
javac Test.java
javap -v Test.class

代码中常见问题
  1. 最低级的错误:单词拼写错误
  2. 要求源文件名字(Test.java)和类名(Test)必须一模一样
  3. 所有的标点必须是英文状态下的
    • 中文状态:【】() {} ! ; : “ ‘ 《》 ?
    • 英文状态:[] () {} ! ; : " ' <> ?
  4. 成对编程:[] {} () <> "" ''
  5. 注意缩进 :只要遇到{}就进行缩进 —>为了格式好看
  6. 编译:javac Test.java
  7. 执行:java Test
  8. Java中大小写严格区分,大小敏感
  9. 一个源文件中可以有多个类,只能有一个类被public修饰,源文件的名字必须跟public修饰的那个类名保持一致
环境变量

classpath 环境变量

JAVA_HOME 环境变量

代码注释

为了方便程序的阅读,Java语言允许程序员在程序中写上一些说明性的文字,用来提高程序的可读性,这些文字性的说明就称为注释;注释不会出现在字节码文件中,即Java编译器编译时会跳过注释语句

  • 单行注释:单行注释使用//开头,//后面的单行内容均为注释
  • 多行注释:多行注释以/*开头以*/结尾,在使用时要注意,多行注释不能嵌套使用
  • 文档注释:文档注释以/**开头以*/结尾,注释中包含一些说明性的文字及一些JavaDoc标签(后期写项目时,可以生成项目的API)

文档注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
文档注释
@author excepenxi
@version 1.0
样例,输出
*/
public class Test{
public static void main(String[] args){
System.out.println("hi....java1");
}
/**
@param name 姓名
@param age 年龄
*/
public void eat(String name,int age){
System.out.println("hello");
}
}

一般文档注释可以配合:jdk提供的工具javadoc.exe来一起使用,通过javadoc.exe可以对文档注释进行解析,生成一套以网页文件形式体现的该程序的说明文档(自定义类对应的API)

1
javadoc -encoding UTF-8  -d myHello -author -version Test.java

输出网页文件

扩展面试题

JDK,JRE,JVM的区别

  • JDK(Java Development Kit)是Java开发工具包,是面向开发者的
  • JRE(Java Runtime Enviroment)是Java的运行环境,面向使用JAVA程序的用户
  • JVM( java virtual machine)是常常听到Java虚拟机

JVM不能单独搞定class的执行,解释class的时候JVM需要调用解释所需要的类库lib。在JDK下面的的jre目录里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre(JVM+Lib=JRE)

具体点就是bin目录下的jvm.dll文件, jvm.dll无法单独工作,当jvm.dll启动后,会使用explicit的方法(就是使用Win32 API之中的LoadLibrary()与GetProcAddress()来载入辅助用的动态链接库),而这些辅助用的动态链接库(.dll)都必须位 于jvm.dll所在目录的父目录之中。因此想使用哪个JVM,只需要设置PATH,指向JRE所在目录下的jvm.dll

数据类型

Java是一种强类型语言,每个变量都必须声明其数据类型
Java的数据类型可分为两大类:基本数据类型(primitive data type)和引用数据类型(reference data type)

PS:巧妙记忆,除了基本数据类型以外的所有类型都属于引用数据类型,这里说一下基本数据类型

标识符
  • 标识符:读音 biao zhi fu
  • 包,类,变量,方法…..等等,只要是起名字的地方,那个名字就是标识符
  • 标识符定义规则
    1. 四个可以(组成部分):数字,字母,下划线_,美元符号$
      • 注意:字母概念比较宽泛,指的是英文字母,汉字,日语,俄语……
      • 一般起名字尽量使用英文字母
    2. 两个不可以:不可以以数字开头,不可以使用java中的关键字
    3. 见名知意:增加可读性
    4. 大小写敏感: int a ; int A;
    5. 遵照驼峰命名
      • 类名:首字母大写,其余遵循驼峰命名
      • 方法名,变量名:首字母小写,其余遵循驼峰命名
      • 包名:全部小写,不遵循驼峰命名
    6. 长度无限制,但是不建议太长 asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasfd
关键字
  • 被JAVA语言赋予了特殊含义,用作专门用途的单词
  • 特点:JAVA中所有关键字都为小写
  • 官网

变量与常量
  • 变量
  • 常量:指的是一个固定的值,主要是利用关键字final来定义一个常量
    • 字面常量:一般将1、2、3、’a’、’b’、true、false、”helloWorld”等称为字面常量
      • 整型常量:123 33
      • 实型常量:3.1415925
      • 字符常量:’a’
      • 逻辑常量:true false
      • 字符串常量:”helloworld”
    • 字符常量:使用final修饰的PI等称为符号常量(字符常量)

变量的声明

如果你只定义一个变量,没有给变量进行赋值的话,那么其实这个变量相当于没有定义

变量如果没有进行赋值的话,那么使用的时候会出错,告诉你:尚未初始化变量

变量定义的时候直接就可以用一句话定义:int age = 10;

变量的值可以更改(age = age+10),变量不可以重复定义(int age=10;int age=20)

变量的作用域

作用域指的就是作用范围,变量在什么范围中有效;作用范围就是离它最近的{}

备注:以下写的代码,不要去运行,会出错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
局部变量:定义在方法中
成员变量:定义在类中,方法外
*/
public class TestVar{
int b = 20;
public static void main(String[] args){
System.out.println(a);//no
int a = 10;
System.out.println(a);//yes
System.out.println(b);//yes
{
int c = 40;
System.out.println(c);//yes
int a = 50;//属于变量的重复定义
}
System.out.println(c);//no
}

public void eat(){
System.out.println(b);//yes
System.out.println(a);//no
int a = 30;//不是变量的重复定义
System.out.println(a);//yes
}
}
整数类型

常量

  • 十进制整数,如:99, -500, 0
  • 八进制整数,要求以 0 开头,如:015
  • 十六进制数,要求 0x 或 0X 开头,如:0x15
  • 二进制:要求0b或者0B开头,如:0b11

几进制:就是逢几进1的问题

平时实际生活中用的最多的是十进制;计算机用二进制最多

变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class TestVar05{
public static void main(String[] args){
//定义整数类型的变量:
//给变量赋值的时候,值可以为不同进制的:
int num1 = 12 ;//默认情况下赋值就是十进制的情况
System.out.println(num1);
int num2 = 012;//前面加上0,这个值就是八进制的
System.out.println(num2);
int num3 = 0x12;//前面加上0x或者0X,这个值就是十六进制的
System.out.println(num3);
int num4 = 0b10;//前面加上0b或者0B,这个值就是二进制的
System.out.println(num4);

//定义byte类型的变量:
byte b = 126;//定义了一个byte类型的变量,名字叫b,赋值为12
System.out.println(b);
//注意:超范围的赋值会报错。
short s = 30000;
System.out.println(s);
int i = 1234;
System.out.println(i);
//整数类型默认就是int类型的,所以12345678910是一个int类型的数,对于int类型来说,它超出范围了
//要想把一个数给long类型变量,那么后面加上L(推荐)或者l就可以了
long num5 = 12345678910L;
System.out.println(num5);
//注意:只有这个数超出int类型的范围了后面才需要加上L,否则无需加L也可以赋值给long类型:
long num6 = 12;
System.out.println(num6);
}
}
浮点类型

常量

  1. 十进制数形式,例如:3.14 314.0 0.314
  2. 科学记数法形式
    • 314e2 314E2 (E的大小写没有区分) 314E-2
    • double f = 314e2; //31410^2–>31400.0
    • double f2 = 314e-2; //31410^(-2)–>3.14

变量

float类型又被称作单精度类型,尾数可以精确到7位有效数字,在很多情况下,float类型的精度很难满足需求。
而double表示这种类型的数值精度约是float类型的两倍,又被称作双精度类型,绝大部分应用程序都采用double类型。
float类型的数值有一个后缀F或者f ,没有后缀F/f的浮点数值默认为double类型。
也可以在浮点数值后添加后缀D或者d, 以明确其为double类型。

PS:有效数字指的是从左开始第一个不为0的数到最后一个数,并不是小数点后开始数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class TestVar{
public static void main(String[] args){
//浮点类型的常量有两种形式:
//十进制形式:
double num1 = 3.14;
System.out.println(num1);
//科学计数法形式:
double num2 = 314E-2;
System.out.println(num2);

//浮点类型的变量:
//注意:浮点型默认是double类型的,要想将一个double类型的数赋给float类型,必须后面加上F或者f
float f1 = 3.14234567898623F;
System.out.println(f1);
//注意:double类型后面可以加D或者d,但是一般我们都省略不写
double d1 = 3.14234567898623D;
System.out.println(d1);

//注意:我们最好不要进行浮点类型的比较:
float f2 = 0.3F;
double d2 = 0.3;
System.out.println(f2==d2); //false 底层存储不同
/*
区别:
= 赋值运算: 将等号右侧的值赋给等号左侧
== 判断==左右两侧的值是否相等 :结果要么相等 要么不相等
== 运算符的结果就是要么是true,要么是false
*/
}
}
字符类型
  1. Java中使用单引号来表示字符常量,字符型在内存中占2个字节
    • char 类型用来表示在Unicode编码表中的字符
    • Unicode编码被设计用来处理各种语言的文字,它占2个字节,可允许有65536个字符
  2. 转义字符

  1. ASCII表

  1. Unicode编码表

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TestVar{
public static void main(String[] args){
//定义字符类型的变量:
char ch1 = 'a';
System.out.println(ch1);
char ch2 = 'A';
System.out.println(ch2);
char ch3 = '4';
System.out.println(ch3);
char ch4 = '中';
System.out.println(ch4);
char ch5 = '?';
System.out.println(ch5);
//java中无论:字母,数字,符号,中文都是字符类型的常量,都占用2个字节。
char ch6 = ' ';
System.out.println(ch6);
//字符类型:单引号引起来的单个字符
System.out.println("--------------------------------");
/*
转义字符:
\将后面的普通字符转换为特殊含义
*/
char ch7 = '\n';
System.out.println("aaa"+ch7+"bbb");

System.out.println("aaa\nbbb");// \n 换行
System.out.println("aaaaaaa\tbbb"); // \t 制表符
System.out.println("aaa\bbbb");//aabbb \b 向前退一格
System.out.println("aaa\rbbb");//bbb \r 将光标到本行开头 :回车
System.out.println("\"java\""); // \" 将双引号原样输出 \' 将单引号原样输出 \\ 将\原样输出
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TestVar{
public static void main(String[] args){
char ch1 = 'A';
System.out.println(ch1);//A
System.out.println(ch1+90);//155
System.out.println(155-ch1);//90
//char类型我们看到的样子就是它本身的字面常量,但是底层在进行计算的时候,
//实际上是按照一个码进行计算的,这个码就是ASCII
//之前说char类型是按照Unicode码表进行存储的
//(Unicode兼容了ASCII码,Unicode的前128位置ASCII)

char ch2 = '中';
System.out.println(ch2);// 中
System.out.println(ch2+90);// 20103
System.out.println(20103-ch2);// 90

//转换:
int num1 = (int)ch2;
System.out.println(num1);//20013

char ch = (char)20013;
System.out.println(ch); //中

int num2 = '中';
char ch5 = 20013;
System.out.println(ch5); //中

//面试题:
char ch6 = '2'+2; // 50+2 52对应ASCII码是4
System.out.println(ch6); //'4'--->4
}
}
布尔类型

boolean类型有两个常量值,true和false,在内存中占一位(不是一个字节),不可以使用 0 或非 0 的整数替代 true 和 false ,这点和C语言不同。 boolean 类型用来判断逻辑条件,一般用于程序流程控制

1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestVar{
public static void main(String[] args){
//创建一个布尔类型的变量:
boolean flag1 = true;
System.out.println(flag1);
boolean flag2 = false;
System.out.println(flag2);
boolean flag3 = 5==9;
System.out.println(flag3);
boolean flag4 = 5<9;
System.out.println(flag4);
}
}
基本数据类型的转换

在赋值运算或者算数运算的时候,要求数据类型一致,就要进行类型的转换

  • 自动转换
  • 强制转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class TestVar{
public static void main(String[] args){
//类型转换的两种形式:
double d = 6;//int-->double 自动类型转换
System.out.println(d);
int i = (int)6.5;//double--->int 强制类型转换 (强转)
System.out.println(i);

//在同一个表达式中,有多个数据类型的时候,应该如何处理:
//多种数据类型参与运算的时候,整数类型,浮点类型,字符类型都可以参与运算,唯独布尔类型不可以参与运算。
//double d2 = 12+1294L+8.5F+3.81+'a'+true;
double d2 = 12+1294L+8.5F+3.81+'a';
System.out.println(d2);
/*
类型级别:(从低到高的)
byte,short,char-->int--->long--->float--->double
级别用来做什么?
当一个表达式中有多种数据类型的时候,要找出当前表达式中级别最高的那个类型,
然后其余的类型都转换为当前表达式中级别最高的类型进行计算。
double d2 = 12+1294L+8.5F+3.81+'a';
= 12.0+1294.0+8.5+3.81+97.0
*/
int i2 = (int)(12+1294L+8.5F+3.81+'a');
System.out.println(i2);
/*
在进行运算的时候:
左=右 : 直接赋值
左<右 :强转
左>右 :直接自动转换
*/

//以下情况属于特殊情形:对于byte,short,char类型来说,
//只要在他们的表数范围中,赋值的时候就不需要进行强转了,直接赋值即可
byte b = 12;
System.out.println(b);
byte b2 = (byte)270;
System.out.println(b2);
}
}

内存演示

习题

实现求圆的周长和面积

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.excepenxi;

import java.util.Scanner;

public class Test2 {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
/*
1.提取变量
2.变量更改为常量:final修饰 字符常量全部大写 PI
*/
final double PI = 3.14;
// 拿来一个扫描器
Scanner sc = new Scanner(System.in);
// 给一个友好性的提示:
System.out.print("请输入一个半径:");
// 让扫描器扫描键盘录入的int类型的数据:
int r = sc.nextInt();
// int r = 5;
// 求周长 2πr 31.400000000000002
double c = 2*PI*r;
System.out.println("周长为:"+c);
// 求面积 πr² 78.5
double s = PI*r*r;
System.out.println("面积为:"+s);
}
}

加深Scanner使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Scanner;
public class TestVar{
public static void main(String[] args){
//键盘录入学生的信息:年龄,身高,姓名,性别:
//键盘录入年龄:(接收int类型数据)
Scanner sc = new Scanner(System.in);
System.out.print("请录入年龄:");
int age = sc.nextInt();
//键盘录入身高:(接收double类型数据)
System.out.print("请录入身高:");
double height = sc.nextDouble();
//键盘录入姓名:(接收String类型数据--》字符串)
System.out.print("请录入姓名:");
String name = sc.next();
//键盘录入性别:(接受char类型)
System.out.print("请录入性别:");
String sexStr = sc.next();
char sex = sexStr.charAt(0);
//上面两句可以合为一句表示:char sex = sc.next().charAt(0);
System.out.println("该学生的信息为:姓名是:"+name+",年龄是:"+age+",身高为:"+height+",性别是:"+sex);
}
}

运算符

  • 算数运算符:+,-,*,/,%,++(自增),--(自减)
  • 赋值运算符:=
  • 扩展赋值运算符:+=,-=,*=,/=
  • 关系运算符:>,<,>=,<=,==,!=
  • 逻辑运算符:&,|, &&,||,!,^
  • 位运算符: &,|,^,~ , >>,<<,>>> (了解!!!)
  • 条件运算符:?:
1
2
3
4
5
# 相关概念辨析
+ 运算符 操作符 Operator
5+6 表达式 expression
5 6 操作数 Operand
int m =5+6; 语句 Sentence

算数运算符
  • / 除法运算符 : 表示两个数相除运算
  • % 取余运算符: 用来求余数的
  • +的作用
    • 表示正数
    • 表示相加操作
    • 进行字符串的拼接
  • ++

无论这个变量是否参与到运算中去,只要用++运算符,这个变量本身就加1操作
只是说如果变量参与到运算中去的话,对运算结果是产生影响:
看++在前还是在后,如果++在后:先运算,后加1 如果++在前,先加1,后运算

1
2
3
4
5
6
7
8
9
public class TestOpe01{
public static void main(String[] args){
//打印结果:
System.out.println(12/3);
System.out.println(12%5);
System.out.println(12/3.0);
System.out.println(12%5.0);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestOpe02{
public static void main(String[] args){
//表示正数:
System.out.println(+5);//5
//相加操作:
System.out.println(5+6);//11
System.out.println(5+'6');//59
//字符串的拼接:
//规则:+左右两侧的任意一侧有字符串,那么这个加号就是字符串拼接的作用,结果一定是字符串
int num = 56;
System.out.println("num="+num);//"num=56" ---> num=56
System.out.println(5+6+"7");//11+"7"--->"117" --->117
System.out.println(5+'6'+"7");//59 +"7"--->"597" --->597
System.out.println("5"+6+"7");//"56"+"7" --->"567"--->567
System.out.println("5"+'6'+"7");//"56"+"7"--->"567"--->567
System.out.println("5"+'6'+'7');//"56"+'7'--->"567"---567
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TestOpe03{
public static void main(String[] args){
int a = 5;
a++;//理解为:相当于 a=a+1 操作
System.out.println(a);//6

a = 5;
++a;//理解为:相当于 a=a+1 操作
System.out.println(a); //6

//总结:++单独使用的时候,无论放在前还是后,都是加1操作

//将++参与到运算中:
//规则:看++在前还是在后,如果++在后:先运算,后加1 如果++在前,先加1,后运算
a = 5;
int m = a++ + 7;//先运算 m=a+7 再加1: a = a+1
System.out.println(m);//12
System.out.println(a);//6

a = 5;
int n = ++a + 7;//先加1 a=a+1 再运算: n = a+7
System.out.println(n);//13
System.out.println(a);//6
}
}
1
2
3
4
5
6
7
8
9
public class TestOpe04{
public static void main(String[] args){
int a = 5;
System.out.println(a++ + a++);
System.out.println(a++ + ++a);
System.out.println(++a + a++);
System.out.println(++a + ++a);
}
}

运算过程

赋值运算符

=的作用: 将等号右侧的值赋给等号左侧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TestOpe06{
public static void main(String[] args){
//任意给出两个数,交换两个数并输出:
//1.给出两个数:
int num1 = 10;
int num2 = 20;

//2.输出交换前的两个数:
System.out.println("交换前:"+num1+"\t"+num2);

//3.交换
/*
错误代码:
num1 = num2;
num2 = num1;
*/
//解决办法:引入一个中间变量:
int t;
t = num1;
num1 = num2;
num2 = t;
/*
int t;
t = num2;
num2 = num1;
num1 = t;
*/

//4.输出交换后的两个数:
System.out.println("交换后:"+num1+"\t"+num2);
}
}

面试题:两个数交换的四种方式

扩展赋值运算符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TestOpe07{
public static void main(String[] args){
//实现功能:给出三个数,求和:
//1.给出三个数:
int num1 = 10;
int num2 = 20;
int num3 = 30;
//2.求和
//int sum = num1+num2+num3;
//定义一个变量,用来接收和:
int sum = 0;
sum = sum + num1;//等效: sum += num1;
sum = sum + num2;// sum += num2;
sum = sum + num3;//sum += num3;
//3.将和输出:
System.out.println("和:"+sum);
}
}
  • a+=b 和 a=a+b 区别:
    • a+=b 可读性稍差 编译效率高 底层自动进行类型转换
    • a=a+b 可读性好 编译效率低 手动进行类型转换

面试题

  1. 请问a+=b相当于a=a+b,那么也相当于 a=b+a吗

  1. 下面的代码哪一句出错: 第4行
1
2
3
4
5
byte a = 10;  --->1
int b = 20; --->2
a+=b; ---->3
a = a+b ;---->4
// 更正: a = (byte)(a+b);
关系运算符
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestOpe08{
public static void main(String[] args){
//>,<,>=,<=,==,!=
//关系运算符最终结果:要么是true要么是false
System.out.println(4>9);//false
System.out.println(4<9);//true
System.out.println(4>=9);//false
System.out.println(4<=9);//true
System.out.println(4==9);//false
System.out.println(4!=9);//true
System.out.println((5<9)!=(6==8));//true
}
}
逻辑运算符

&,|, &&,||,!,^

逻辑运算符:进行逻辑运算的,运算符左右连接的都是 布尔类型的操作数,最终表达式的结果是布尔值:要么是true,要么false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class TestOpe09{
public static void main(String[] args){
// 逻辑与 :& 规律:只要有一个操作数是false,那么结果一定是false
System.out.println(true&true);
System.out.println(true&false);
System.out.println(false&false);
System.out.println(false&true);

// 短路与:&& 规律:效率高一些,只要第一个表达式是false,那么第二个表达式就不用计算了,结果一定是false
System.out.println(true&&true);
System.out.println(true&&false);
System.out.println(false&&false);
System.out.println(false&&true);

// 逻辑或:| 规律:只要有一个操作数是true,那么结果一定是true
System.out.println(true|true);
System.out.println(true|false);
System.out.println(false|false);
System.out.println(false|true);

// 短路或:|| 规律:效率高一些,只要第一个表达式是true,那么第二个表达式就不用计算了,结果一定是true
System.out.println(true||true);
System.out.println(true||false);
System.out.println(false||false);
System.out.println(false||true);

//逻辑非: ! 规律:相反结果
System.out.println(!true);//false
System.out.println(!false);//true

//逻辑异或: ^ 规律:两个操作数相同,结果为false,不相同,结果为true
System.out.println(true^true);
System.out.println(true^false);
System.out.println(false^false);
System.out.println(false^true);
}
}

再做一个加深的练习:看代码 说结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TestOpe10{
public static void main(String[] args){
int i=8;
System.out.println((5>7)&&(i++==2)); //false
System.out.println(i); //8

int a=8;
System.out.println((5>7)&(a++==2)); //false
System.out.println(a); //9

int m=8;
System.out.println((5<7)&&(m++==2)); //false
System.out.println(m); //9

int b=2;
System.out.println((5<7)&(b++==2)); //true
System.out.println(b); //3

int c=2;
System.out.println((5<7)&(++c==2)); //false
System.out.println(c); //3
}
}
条件运算符

条件运算符:又称三元运算符/三目运算符

格式:a?b:c

其中a是一个布尔类型的表达式,返回结果要么是true要么false,通过a的结果决定最终表达式的结果:
如果a的结果是true,那么表达式最终结果为b
如果a的结果是false,那么表达式最终结果为c

1
2
3
4
5
6
7
8
9
10
11
public class TestOpe11{
public static void main(String[] args){
int num = (5>7)?6:9 ;
System.out.println(num);

String str = (4==4)?"你好":"你不好" ;
System.out.println(str);

System.out.println((4==4)?"你好":"你不好");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.*;//*代表所有
public class TestOpe12{
public static void main(String[] args){
//实现功能:男孩女孩选择晚饭吃什么,如果意见一致,听男生的,如果意见不一致,听女生的

//1.要让男孩女孩选择晚饭吃什么:
Scanner sc = new Scanner(System.in);
System.out.println("请选择今晚吃什么:1.火锅 2.烧烤 3.麻辣烫 4.西餐");
System.out.println("请男孩选择:");
int boyChoice = sc.nextInt();
System.out.println("请女孩选择:");
int girlChoice = sc.nextInt();
//2.判断:
System.out.println(boyChoice==girlChoice?"听男孩的":"听女孩的");
}
}

PS:三目运算符可以代替后续的if-else

位运算符

&,|,^,~ , >>,<<,>>>

如何区分逻辑运算符和位运算符:
逻辑运算符:左右连接的是布尔类型的操作数
位运算符:左右连接的是具体的数值

流程控制

if分支结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
if-单分支:
(1)结构:
if(条件表达式,这个表达式的结果是布尔值:要么是false,要么是true){
//如果上面()中的表达式返回结果是true,那么执行{}中代码
//如果上面()中的表达式返回结果是false ,那么不执行{}中代码
//PS:{}中的代码是否执行,取决于()中表达式的返回结果
}
(2)上面的代码中,我用四个单分支拼凑出四个选择,每个选择是独立的,依次判断执行的
(3)if后面的()中的条件,要按照自己需求尽量完善
(4){}可以省略不写,但是一旦省略,这个if就只负责后面的一句话,所以我们不建议初学者省略

if-多分支:
【1】结构:
if(){
}else if(){
}else if(){
}...
else{
}
【2】else:隐藏了一个条件,跟上面分支条件表达式相反的功能
【3】多分支:好处:只要满足一个 分支以后,后面的分支就不需要判断了 --》效率高
【4】我们写代码的时候,尽量保证else的存在--》else分支相当于“兜底”“备胎”的作用,别的分支都不走,就会走这个分支了

if-双分支:
【1】结构
if(布尔表达式){
语句块1
}else{
语句块2
}
*/

实现一个功能:给出三个数(1-6),对三个数求和计算,根据和的大小来分配不同的奖品

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.excepenxi;

public class Test5_if {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
// 生成随机数:这个数在生成之前我们不确定这个数是多少,不可知
/*
Math.random() -------> [0.0,1.0)
Math.random()*6 ----->[0.0,6.0)
(int)(Math.random()*6) ----->[0,5]
(int)(Math.random()*6) +1 ----->[1,6]
*/
int num1 = (int)(Math.random()*6) +1; //[1,6] ==> [0,5] +1
int num2 = (int)(Math.random()*6) +1;
int num3 = (int)(Math.random()*6) +1;
int sum = 0;
// System.out.println(sum+=num1+=num2+=num3);
sum+=num1+=num2+=num3;
if (sum<=14 && sum>=10) {
System.out.println("一等奖");
}else if (sum<10 && sum>=6){
System.out.println("三等奖");
}else if (sum<6){
System.out.println("四等奖");
}else {
System.out.println("未中奖");
}
System.out.println(sum>=10?"中奖了":"没中奖");

}
}

程序的优化:会员购物时,不同积分享受的折扣不同,规则如下

会员积分x 折扣
x≥8000 6折
4000≤x<8000 7折
2000≤x<4000 8折
x<2000 9折
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.excepenxi;

import java.util.Scanner;

public class Test6_if {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入会员积分:");
if (sc.hasNextInt()==true) {
int score = sc.nextInt();
if (score>=0) {
String discount = "";
if (score >= 8000) {
discount = "0.6";
} else if (score >= 4000) {
discount = "0.7";
} else if (score >= 2000) {
discount = "0.8";
} else {
discount = "0.9";
}
System.out.println("该会员享受的折扣是:"+discount);
}else {
System.out.println("您输入的是负数,不符合需求!!!");
}
}else {
System.out.println("会员积分请输入整数!!!");
}
}
}

逻辑题:小朋友搬桌子

年龄大于7岁,可以搬桌子;
如果年龄大于5岁,性别是男,可以搬桌子;
否则不可以搬动桌子,提示:你还太小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.excepenxi;

import java.util.Scanner;

public class Test7_if {
// 这是一个main方法,是程序的入口
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入你的年龄:");
if (sc.hasNextInt()==true) {
int age = sc.nextInt();
if (age>=0){
if (age>=7) {
System.out.println("搬桌子");
}else if (age>=5){
System.out.print("请输入你的性别 男为1,女为0:");
int sex = sc.nextInt();
if (sex==1) {
System.out.println("男,可搬桌子");
}else if (sex==0){
System.out.println("女,不可搬桌子");
}else {
System.out.println("性别请输入0或1");
}
}else {
System.out.println("你还太小");
}
}else {
System.out.println("请输入正数!!!");
}
}else {
System.out.println("输入错误!!!");
}
}
}
switch多分支结构
1
2
3
4
5
6
7
8
9
10
switch (表达式) {
case1:
语句序列1;
[break];
case2:
语句序列2;
[break];
… … … … …
[default:默认语句;]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
【1】语法结构:
switch(){
case * :
case * :
.......
}
【2】switch后面是一个(),()中表达式返回的结果是一个等值,这个等值的类型可以为:
int,byte,short,char,String,枚举类型
【3】这个()中的等值会依次跟case后面的值进行比较,如果匹配成功,就执行:后面的代码
【4】为了防止代码的“穿透”效果:在每个分支后面加上一个关键词break,遇到break这个分支就结束了
【5】类似else的“兜底”“备胎”的分支:default分支
【6】default分支可以写在任意的位置上,但是如果没有在最后一行,后面必须加上break关键字,如果在最后一行的话,break可以省略
【7】相邻分支逻辑是一样的,那么就可以只保留最后一个分支,上面的都可以省去不写了
【8】switch分支和if分支区别:
表达式是等值判断的话--》if ,switch都可以
如果表达式是区间判断的情况---》if最好
【9】switch应用场合:就是等值判断,等值的情况比较少的情况下
*/

switch语句会根据表达式的值从相匹配的case标签处开始执行,一直执行到break语句处或者是switch语句的末尾。如果表达式的值与任一case值不匹配,则进入default语句(如果存在default语句的情况)。根据表达式值的不同可以执行许多不同的操作。switch语句中case标签在JDK1.5之前必须是整数(long类型除外)或者枚举,不能是字符串,在JDK1.7之后允许使用字符串(String)。大家要注意,当布尔表达式是等值判断的情况,可以使用if-else if-else多分支结构或者switch结构,如果布尔表达式区间判断的情况,则只能使用if-else if-else多分支结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class TestSwitch{
public static void main(String[] args){
/*
实现一个功能:
根据给出的学生分数,判断学生的等级:
>=90 -----A
>=80 -----B
>=70 -----C
>=60 -----D
<60 -----E

用if分支:
if(score>=90){
}else if(score>=80){
}
*/
//1.给出学生的成绩:
int score = 86;
//2.根据成绩判断学生的等级:
switch(score/10){
case 10 :
case 9 : System.out.println("A级");break;
case 8 : System.out.println("B级");break;
case 7 : System.out.println("C级");break;
case 6 : System.out.println("D级");break;
default:System.out.println("成绩错误");break;
case 5 :
case 4 :
case 3 :
case 2 :
case 1 :
case 0 : System.out.println("E级");break;
}
}
}
while循环
1
2
3
4
5
6
7
8
9
10
11
while (布尔表达式) {
循环体;
}
/*
【1】循环作用:将部分代码重复执行;循环只是提高了程序员编写代码的效率,但是底层执行的时候依然是重复执行
【2】循环四要素
1.条件初始化:int num = 1;
2.条件判断:while(num<=5)
3.循环体:sum += num;
4.迭代: num++;
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestWhile{
public static void main(String[] args){
//功能:1+2+3+4+5
//1.定义变量:
int num = 1;
//2.定义一个求和变量,用来接收和:
int sum = 0;
while(num<=5){
sum += num;
num++;
}
//3.输出和
System.out.println(sum);
}
}

练习

  • 1+2+3+4+5+。。。。+100
  • 2+4+6+8+。。。。+998+1000
  • 5+10+15+20+。。。+100
  • 99+97+95+。。5+3+1
  • 1*3*5*7*9*11*13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class TestWhile02{
public static void main(String[] args){
/*
//【1】1+2+3+4+5+。。。。+100
int i = 1;
int sum = 0;
while(i<=100){
sum += i;
i++;
}
System.out.println(sum);
//【2】2+4+6+8+。。。。+998+1000
int i = 2;
int sum = 0;
while(i<=1000){
sum += i;
i = i+2;
}
System.out.println(sum);
//【3】5+10+15+20+。。。+100
int i = 5;
int sum = 0;
while(i<=100){
sum += i;
i = i+5;
}
System.out.println(sum);

//【4】99+97+95+。。5+3+1
int i = 99;
int sum = 0;
while(i>=1){
sum += i;
i = i-2;
}
System.out.println(sum);
*/
//【5】1*3*5*7*9*11*13
int i = 1;
int result = 1;
while(i<=13){
result *= i;
i = i+2;
}
System.out.println(result);
}
}
do-while循环
1
2
3
do {
循环体;
} while(布尔表达式) ;

do-while循环结构会先执行循环体,然后再判断布尔表达式的值,若条件为真,执行循环体,当条件为假时,结束循环。do-while循环的循环体至少执行一次

1
2
3
4
5
6
7
8
9
10
11
12
13
// while和do-while的区别
while:先判断,再执行
do-while:先执行,再判断---》至少被执行一次,从第二次开始才进行判断

// 什么场合使用do-while:
// ---》不合适
while(考试是否通过){
考试;
}
// ---》合适
do{
考试;
}while(考试是否通过);

练习:1+2+3+4+...100

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TestDoWhile{
public static void main(String[] args){
// while方式:
/*
int i = 101;
int sum = 0;
while(i<=100){
sum += i;
i++;
}
System.out.println(i);//101
System.out.println(sum);//0
*/

//do-while方式:
int i = 101;
int sum = 0;
do{
sum += i;
i++;
}while(i<=100); //一定要注意写这个分号,否则编译出错
System.out.println(i);//102
System.out.println(sum);//101
}
}
for循环

for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。for循环在第一次反复之前要进行初始化,即执行初始表达式;随后,对布尔表达式进行判定,若判定结果为true,则执行循环体,否则,终止循环;最后在每一次反复的时候,进行某种形式的“步进”,即执行迭代因子

  1. 初始化部分设置循环变量的初值
  2. 条件判断部分为任意布尔表达式
  3. 迭代因子控制循环变量的增减

for循环在执行条件判定后,先执行的循环体部分,再执行步进

for循环结构的流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 【1】for的结构:
for (初始表达式; 布尔表达式; 迭代因子) {
循环体;
}
// 【2】i的作用域:作用范围:离变量最近{} --->可以自己去控制
// 【3】for循环格式特别灵活:格式虽然很灵活,但是我们自己写代码的时候不建议灵活着写
for(;;){} -->死循环

int i = 1;
for(;i<=100;){
sum += i;
i++;
}
// 【4】死循环:
for(;;){}
while(true){}
do{
}while(true);
// 【5】循环分为两大类:
第一类:当型 while(){} for(;;){}
第二类:直到型 do{}while();
// 【6】以后常用:for循环
// 【7】do-while,while,for循环谁的效率高? 一样高

练习:1+2+3+..+100

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TestFor{
public static void main(String[] args){
//while:
/*
int i = 1;
int sum = 0;
while(i<=100){
sum += i;
i++;
}
System.out.println(sum);*/

//for:
int sum = 0;
int i;
for(i = 1;i<=100;i++){
sum += i;
}
System.out.println(sum);
System.out.println(i);
}
}
关键字:break、continue、return

在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestFor03{
public static void main(String[] args){
//break的作用:停止最近的循环
/*
for(int i=1;i<=100;i++){
System.out.println(i);
if(i==36){
break;//1-36
}
}
*/
for(int i=1;i<=100;i++){
System.out.println(i);
while(i==36){
break; //1-100 ---》break停止的是while循环,而不是外面的for循环
}
}
}
}

break带标签的使用

1
2
3
4
5
6
7
8
9
10
11
12
public class TestFor04{
public static void main(String[] args){
// outer标签名字自定义,位置自定义,名字不能重复
outer: // 定义标签结束的位置
for(int i=1;i<=100;i++){
System.out.println(i);
while(i==36){
break outer; // 根据标签来结束循环
}
}
}
}

continue的作用:在循环语句体中,用于终止某次循环过程,结束本次循环,继续下一次循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestFor06{
public static void main(String[] args){
//continue:结束本次离它近的循环,继续下一次循环
/*
for(int i=1;i<=100;i++){
if(i==36){
continue;//1-100中间没有36
}
System.out.println(i);
}
*/
for(int i=1;i<=100;i++){
while(i==36){
System.out.println("------");
continue; //1-35+死循环
}
System.out.println(i);
}
}
}

continue带标签的使用

1
2
3
4
5
6
7
8
9
10
11
12
public class TestFor07{
public static void main(String[] args){
// outer标签名字自定义,位置自定义,名字不能重复
outer:
for(int i=1;i<=100;i++){
while(i==36){
continue outer; //1-100没有36
}
System.out.println(i);
}
}
}

return的作用:跟循环无关,就是程序中遇到return那么return所在的那个方法就停止执行了

1
2
3
4
5
6
7
8
9
10
11
12
public class TestFor08{
public static void main(String[] args){
//return:遇到return结束当前正在执行的方法
for(int i=1;i<=100;i++){
while(i==36){
return;
}
System.out.println(i);
}
System.out.println("-----");
}
}
循环练习

输出1-100中被5整除的数,每行输出6个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestFor09{
public static void main(String[] args){
//引入一个计数器:
int count = 0;//初始值为0
for(int i=1;i<=100;i++){
if(i%5==0){//被5整除的数
System.out.print(i+"\t");
count++;//每在控制台输出一个数,count就加1操作
if(count%6==0){
System.out.println();//换行
}
}
}
}
}

实现一个功能

  • 请录入10个整数,当输入的数是666的时候,退出程序
  • 判断其中录入正数的个数并输出
  • 判断系统的退出状态:是正常退出还是被迫退出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.Scanner;
public class TestFor10{
public static void main(String[] args){
//引入一个计数器:
int count = 0;
//引入一个布尔类型的变量:
boolean flag = true; //---》理解为一个“开关”,默认情况下开关是开着的
Scanner sc = new Scanner(System.in);
for(int i=1;i<=10;i++){//i:循环次数
System.out.println("请录入第"+i+"个数:");
int num = sc.nextInt();
if(num>0){//录入的正数
count++;
}
if(num==666){
flag = false;//当遇到666的时候,“开关”被关上了
//退出循环:
break;
}
}
System.out.println("你录入的正数的个数为:"+count);

if(flag){//flag==true
System.out.println("正常退出!");
}else{//flag==false
System.out.println("被迫退出!");
}
}
}
双重循环
  • 乘法口诀
  • 打印各种形状

乘法口诀

1
2
3
4
5
6
7
8
9
10
// 乘法口诀
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class TestFor11{
public static void main(String[] args){
//1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
/*
System.out.print("1*6=6"+"\t");
System.out.print("2*6=12"+"\t");
System.out.print("3*6=18"+"\t");
System.out.print("4*6=24"+"\t");
System.out.print("5*6=30"+"\t");
System.out.print("6*6=36"+"\t");

for(int i=1;i<=6;i++){
System.out.print(i+"*6="+i*6+"\t");
}
//换行
System.out.println();

//1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
for(int i=1;i<=7;i++){
System.out.print(i+"*7="+i*7+"\t");
}
//换行
System.out.println();

//1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
for(int i=1;i<=8;i++){
System.out.print(i+"*8="+i*8+"\t");
}
//换行
System.out.println();
*/

for(int j=1;j<=9;j++){
for(int i=1;i<=j;i++){
System.out.print(i+"*"+j+"="+i*j+"\t");
}
//换行
System.out.println();
}
}
}
1
2
3
4
5
6
7
8
9
1*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*4=4 2*4=8 3*4=12 4*4=16
1*3=3 2*3=6 3*3=9
1*2=2 2*2=4
1*1=1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class TestFor12{
public static void main(String[] args){
/*
//1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
for(int i=1;i<=8;i++){
System.out.print(i+"*8="+i*8+"\t");
}
//换行
System.out.println();

//1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
for(int i=1;i<=7;i++){
System.out.print(i+"*7="+i*7+"\t");
}
//换行
System.out.println();

//1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
for(int i=1;i<=6;i++){
System.out.print(i+"*6="+i*6+"\t");
}
//换行
System.out.println();
*/

for(int j=9;j>=1;j--){
for(int i=1;i<=j;i++){
System.out.print(i+"*"+j+"="+i*j+"\t");
}
//换行
System.out.println();
}
}
}

打印各种形状

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 长方形
for(int j=1;j<=4;j++){//j:控制行数
//*********
for(int i=1;i<=9;i++){//i:控制*的个数
System.out.print("*");
}
//换行:
System.out.println();
}

// 有一定空隙的长方形
for(int j=1;j<=4;j++){//j:控制行数
//加入空格:
for(int i=1;i<=5;i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=9;i++){//i:控制*的个数
System.out.print("*");
}
//换行:
System.out.println();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 平行四边形 
for(int j=1;j<=4;j++){//j:控制行数
//加入空格:
for(int i=1;i<=(9-j);i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=9;i++){//i:控制*的个数
System.out.print("*");
}
//换行:
System.out.println();
}

// 三角形
for(int j=1;j<=4;j++){//j:控制行数
//加入空格:
for(int i=1;i<=(9-j);i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=(2*j-1);i++){//i:控制*的个数
System.out.print("*");
}
//换行:
System.out.println();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 实心菱形
//上面三角形:
for(int j=1;j<=4;j++){//j:控制行数
//加入空格:
for(int i=1;i<=(9-j);i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=(2*j-1);i++){//i:控制*的个数
System.out.print("*");
}
//换行:
System.out.println();
}
//下面三角形:
for(int j=1;j<=3;j++){//j:控制行数
//加入空格:
for(int i=1;i<=(j+5);i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=(7-2*j);i++){//i:控制*的个数
System.out.print("*");
}
//换行:
System.out.println();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 空心菱形
//上面三角形:
for(int j=1;j<=4;j++){//j:控制行数
//加入空格:
for(int i=1;i<=(9-j);i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=(2*j-1);i++){//i:控制*的个数
if(i==1||i==(2*j-1)){
System.out.print("*");
}else{
System.out.print(" ");
}
}
//换行:
System.out.println();
}
//下面三角形:
for(int j=1;j<=3;j++){//j:控制行数
//加入空格:
for(int i=1;i<=(j+5);i++){//i:控制空格的个数
System.out.print(" ");
}
//*********
for(int i=1;i<=(7-2*j);i++){//i:控制*的个数
if(i==1||i==(7-2*j)){
System.out.print("*");
}else{
System.out.print(" ");
}
}
//换行:
System.out.println();
}

菱形第二种打印方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 实心菱形
public class TestFor14{
public static void main(String[] args){
//先打印出一个正方形,然后某些位置上打印* 某些位置上打印空格:
int size = 17;
int startNum = size/2+1;//起始列号
int endNum = size/2+1;//结束列号
//引入一个布尔类型的变量---》理解为“开关”
boolean flag = true;
for(int j=1;j<=size;j++){
//*****
for(int i=1;i<=size;i++){
if(i>=startNum&&i<=endNum){
System.out.print("*");
}else{
System.out.print(" ");
}
}
//换行
System.out.println();
if(endNum==size){
flag = false;
}

if(flag){//flag是true相当于在菱形的上半侧 flag是false相当于在菱形的下半侧
startNum--;
endNum++;
}else{
startNum++;
endNum--;
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 空心菱形
public class TestFor14{
public static void main(String[] args){
//先打印出一个正方形,然后某些位置上打印* 某些位置上打印空格:
int size = 17;
int startNum = size/2+1;//起始列号
int endNum = size/2+1;//结束列号
//引入一个布尔类型的变量---》理解为“开关”
boolean flag = true;
for(int j=1;j<=size;j++){
//*****
for(int i=1;i<=size;i++){
if(i==startNum||i==endNum){
System.out.print("*");
}else{
System.out.print(" ");
}
}
//换行
System.out.println();
if(endNum==size){
flag = false;
}

if(flag){//flag是true相当于在菱形的上半侧 flag是false相当于在菱形的下半侧
startNum--;
endNum++;
}else{
startNum++;
endNum--;
}
}
}
}
三重循环

二重循环可以帮我们解决:二元一次方程组的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1<=a<=5
// 3<=b<=6
// a+b=?
public class TestFor15{
public static void main(String[] args){
for(int a=1;a<=5;a++){
for(int b=3;b<=6;b++){
if(a+b==7){
System.out.println(a+"----"+b);
}
}
}
}
}

三重循环可以帮我们解决:三元一次方程组的问题

  • 百钱买百鸡

百钱买百鸡

1
2
3
4
5
6
7
8
9
10
/*
公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用100文钱买一百只鸡;
其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱
数学:设未知数
公鸡:x只
母鸡:y只
小鸡:z只
x+y+z=100只
5x+3y+z/3=100钱
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class TestFor16{
public static void main(String[] args){
// 麻烦方式:
/*
for(int x=1;x<=100;x++){
for(int y=1;y<=100;y++){
for(int z=1;z<=100;z++){
if((x+y+z==100)&&(5*x+3*y+z/3==100)&&(z%3==0)){
System.out.println(x+"\t"+y+"\t"+z);
}
}
}
}
*/

//优化:
for(int x=1;x<=19;x++){
for(int y=1;y<=31;y++){
int z = 100-x-y;
if((5*x+3*y+z/3==100)&&(z%3==0)){
System.out.println(x+"\t"+y+"\t"+z);
}
}
}
}
}

方法的定义、调用、重载

  • 方法(method)就是一段用来完成特定功能的代码片段,类似于其它语言的函数(function)
  • 方法用于定义该类或该类的实例的行为特征和功能实现,方法是类和对象行为特征的抽象
  • 方法很类似于面向过程中的函数;面向过程中,函数是最基本单位,整个程序由一个个函数调用组成
  • 面向对象中,整个程序的基本单位是类,方法是从属于类和对象的
方法的定义、调用
1
2
3
4
5
6
// 方法声明格式
[修饰符1 修饰符2 …] 返回值类型 方法名(形式参数列表){
Java语句;… … …
}
// 方法的调用方式
对象名.方法名(实参列表)
  • 形式参数:在方法声明时用于接收外界传入的数据
  • 实参:调用方法时实际传给方法的数据
  • 返回值:方法在执行完毕后返还给调用它的环境的数据
  • 返回值类型:事先约定的返回值的数据类型,如无返回值,必须显示指定为为void
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class TestMethod01{
//方法的定义:(写方法)
public static int add(int num1,int num2){
int sum = 0;
sum += num1;
sum += num2;
return sum;//将返回值返回到方法的调用处
}

public static void main(String[] args){
//10+20:
//方法的调用:(用方法)
int num = add(10,20);
System.out.println(num);
/*
int num1 = 10;
int num2 = 20;
int sum = 0;
sum += num1;
sum += num2;
System.out.println(sum);
*/
//30+90:
int sum = add(30,90);
System.out.println(sum);
//50+48:
System.out.println(add(50,48));
}
}
  1. 方法是:对特定的功能进行提取,形成一个代码片段,这个代码片段就是我们所说的方法
  2. 方法和方法是并列的关系,所以我们定义的方法不能写到main方法中
  3. 方法的定义–》格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
修饰符 方法返回值类型 方法名(形参列表){
方法体;
return 方法返回值;
}
对象名.方法名(实参列表)
public static int add(int num1,int num2){
int sum = 0;
sum += num1;
sum += num2;
return sum;
}
public static void main(String[] args){
System.out.println(add(50,48));
}
  1. 方法的作用:提高代码的复用性
  2. 总结方法定义的格式:
    1. 修饰符: 暂时使用public static —>具体查看面向对象
    2. 方法返回值类型 : 方法的返回值对应的数据类型
      • 数据类型: 可以是基本数据类型(byte,short,int,long,float,double,char,boolean)
      • 也可以是引用数据类型
    3. 方法名 :见名知意,首字母小写,其余遵循驼峰命名, eg: addNum ,一般尽量使用英文来命名
    4. 形参列表 :方法定义的时候需要的形式参数
      • int num1, int num2 –>相当于告诉方法的调用者:需要传入几个参数,需要传入的参数的类型
      • 实际参数:方法调用的时候传入的具体的参数: 10,20 –>根据形式参数的需要传入的
    5. 方法体:具体的业务逻辑代码
    6. return 方法返回值
      • 方法如果有返回值的话: return+方法返回值,将返回值返回到方法的调用处
      • 方法没有返回值的话:return可以省略不写了,并且方法的返回值类型为:void
      • 什么时候有返回值,什么时候没有返回值? 看心情–》看需求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestMethod02{
public static void add(int num1,int num2){
int sum = 0;
sum += num1;
sum += num2;
System.out.println(sum);
//return;
}
public static void main(String[] args){
//10+20:
//方法的调用:(用方法)
add(10,20);
//30+90:
add(30,90);
//50+48:
//报错:TestMethod02.java:22: 错误: 此处不允许使用 '空' 类型
//System.out.println(add(50,48));
}
}
  1. 方法的定义需要注意什么?
    • 形参列表要怎么写:定义几个参数,分别是什么类型的 —》不确定因素我们会当做方法的形参
    • 方法到底是否需要返回值 ,如果需要的话,返回值的类型是什么
  2. 方法的调用需要注意什么?
    • 实际参数要怎么传入:传入几个参数,传入什么类型的
    • 方法是否有返回值需要接收
练习

功能:我心里有一个数,你来猜,看是否猜对

TestMethod03
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Scanner;
public class TestMethod03{
public static void main(String[] args){
//1.你猜一个数
Scanner sc = new Scanner(System.in);
System.out.print("请你猜一个数:");
int yourGuessNum = sc.nextInt();
//2.我心里有一个数
int myHeartNum = 5;
//3.将两个数比对:
System.out.println(yourGuessNum==myHeartNum?"猜对了":"猜错了");
}
}

对猜数功能提取为一个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.Scanner;
public class TestMethod03{
public static void main(String[] args){
//1.你猜一个数
Scanner sc = new Scanner(System.in);
System.out.print("请你猜一个数:");
int yourGuessNum = sc.nextInt();
//调用猜数的方法:
guessNum(yourGuessNum);
}
//方法的定义:功能:实现猜数功能:
public static void guessNum(int yourNum){
//我心里有一个数(1-6) 随机数
int myHeartNum = (int)(Math.random()*6)+1;
//将两个数比对:
System.out.println(yourNum==myHeartNum?"猜对了":"猜错了");
}
}
  • 面试题:请问下面代码中两个数是否交换成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestM{
public static void main(String[] args){
int a=10;
int b=20;
System.out.println("输出交换前的两个数:"+a+"---"+b);
changeNum(a,b);
System.out.println("输出交换后的两个数:"+a+"---"+b);
}
public static void changeNum(int num1,int num2){
int t;
t=num1;
num1=num2;
num2=t;
}
}
1
2
3
4
5
// 结果:没有交换成功
输出交换前的两个数:10---20
输出交换后的两个数:10---20

// 原因:看下图,并没有改变a和b,只交换了num1、num2

方法的重载

方法的重载是指一个类中可以定义多个方法名相同,但参数不同的方法。 调用时,会根据不同的参数自动匹配对应的方法。

注意本质:重载的方法,实际是完全不同的方法,只是名称相同而已!

  • 构成方法重载的条件:
    • 不同的含义:形参类型、形参个数、形参顺序不同
    • 只有返回值不同不构成方法的重载
      • 如:int a(String str){}与 void a(String str){}不构成方法重载
    • 只有形参的名称不同,不构成方法的重载
      • 如:int a(String str){}与int a(String s){}不构成方法重载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class TestMethod05{
public static void main(String[] args){
//10+20:
int sum = add(10,20);
System.out.println(sum);

//20+40+80:
//System.out.println(add(add(20,40),80));
System.out.println(add(20,40,80));
//30+60+90+120:
//System.out.println(add(add(30,60),add(90,120)));
System.out.println(add(30,60,90,120));
//9.8+4.7:
//System.out.println(add(9.8,4.7));
System.out.println(add(9.8,4.7));
}

//定义一个方法:两个数相加:两个int类型数据相加
public static int add(int num1,int num2){
return num1+num2;
}
//定义一个方法:三个数相加:
public static int add(int num1,int num2,int num3){
return num1+num2+num3;
}
//定义一个方法:四个数相加:
public static int add(int num1,int num2,int num3,int num4){
return num1+num2+num3+num4;
}
//定义一个方法:两个数相加:两个double类型的数据相加
public static double add(double num1,double num2){
return num1+num2;
}
}
  1. 方法的重载:在同一个类中,方法名相同,形参列表不同的多个方法,构成了方法的重载
  2. 方法的重载只跟:方法名和形参列表有关,与修饰符,返回值类型无关
  3. 注意:形参列表不同指的是什么?
    1. 个数不同
      • add() add(int num1) add(int num1,int num2)
    2. 顺序不同
      • add(int num1,double num2) add(double num1,int num2)
    3. 类型不同
      • add(int num1) add(double num1)
  4. 请问下面的方法是否构成了方法的重载?
    1. add(int a) 和 add(int b) —>不构成,相当于方法的重复定义
    2. public static int add(int a) 和 public static void add(int b) —>不构成

扩展

TestMethod06
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TestMethod06{
public static void main(String[] args){
add(5);
// 走和int临近的long
//级别:byte,short,char-->int-->long-->float--->double
}

public static void add(double num1){
System.out.println("------2");
}
public static void add(float num1){
System.out.println("------3");
}
public static void add(long num1){
System.out.println("------4");
}
/*
public static void add(int num1){
System.out.println("------1");
}
*/
}

数组

定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.Scanner;
public class TestArray01{
public static void main(String[] args){
//功能:键盘录入十个学生的成绩,求和,求平均数:
//定义一个求和的变量:
int sum = 0;
Scanner sc = new Scanner(System.in);
for(int i=1;i<=10;i++){//i:控制循环次数
System.out.print("请录入第"+i+"个学生的成绩:");
int score = sc.nextInt();
sum += score;
}

System.out.println("十个学生的成绩之和为:"+sum);
System.out.println("十个学生的成绩平均数为:"+sum/10);
//本题的缺点:
//求第6个学生的成绩:?????---》不能
}
}
  • 缺点:就是不能求每个学生的成绩具体是多少

  • 解决:将成绩进行存储 —-》 引入 : 数组

数组的作用:数组用来存储数据的,在程序设计中,为了处理方便,数组用来将相同类型的若干数据组织起来,这个若干数据的集合我们称之为数组

数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问它们

  • 数组的四个基本特点:
    1. 长度是确定的。数组一旦被创建,它的大小就是不可以改变的
    2. 其元素的类型必须是相同类型,不允许出现混合类型
    3. 数组类型可以是任何数据类型,包括基本类型和引用类型
    4. 数组有索引的:索引从0开始,到 数组.length-1 结束
    5. 数组变量属于引用类型,数组也是对象
  • PS:数组变量属于引用类型,数组也是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中存储的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class TestArray02{
public static void main(String[] args){
//数组的作用:用来存储相同类型的数据
//以int类型数据为案例:数组用来存储int类型数据
//1.声明(定义数组)
//定义一个int类型的数组,名字叫arr
int[] arr; //或者 int arr[];
//如果数组只声明,没有后续操作,那么这个数组相当于没定义
//int[] arr3 = null;
//空 辨别:数组赋值为null和什么都没有赋值,不一样的效果

//2.创建
arr = new int[4];//给数组开辟了一个长度为4的空间
//编译期声明和创建会被合为一句话: int[] arr = new int[4];

//3.赋值
arr[0] = 12;
arr[3] = 47;
arr[2] = 98;
arr[1] = 56;
arr[2] = 66; //覆盖98
/*
arr[4] = 93;
出现异常:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
Array 数组
Index 索引
OutOf 超出
Bounds 界限
Exception 异常
---》数组索引越界异常
*/

//4.使用
System.out.println(arr[2]);
System.out.println(arr[0]+100);
//通过数组一个属性来获取 length 长度 上方定义的int[4]
System.out.println("数组的长度是:"+arr.length);
}
}

内存分析

数组遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.util.Scanner;
public class TestArray03{
public static void main(String[] args){
//功能:键盘录入十个学生的成绩,求和,求平均数:
//定义一个int类型的数组,长度为10 :
int[] scores = new int[10];
//定义一个求和的变量:
int sum = 0;
Scanner sc = new Scanner(System.in);
for(int i=1;i<=10;i++){//i:控制循环次数
System.out.print("请录入第"+i+"个学生的成绩:");
int score = sc.nextInt();
scores[i-1] = score;
sum += score;
}

System.out.println("十个学生的成绩之和为:"+sum);
System.out.println("十个学生的成绩平均数为:"+sum/10);

//求第6个学生的成绩:
//System.out.println(scores[5]);
/*
System.out.println(scores[0]);
System.out.println(scores[1]);
System.out.println(scores[2]);
System.out.println(scores[3]);
//....
System.out.println(scores[9]);
*/
//将数组中的每个元素进行查看--》数组的遍历:
//方式1:普通for循环---》正向遍历:
for(int i=0;i<=9;i++){
System.out.println("第"+(i+1)+"个学生的成绩为:"+scores[i]);
}

//方式2:增强for循环:
//对scores数组进行遍历,遍历出来每个元素都用int类型的num接收:
int count = 0;
for(int num:scores){
count++;
//每次都将num在控制台输出
System.out.println("第"+count+"个学生的成绩为:"+num);
}
/*
增强for循环:
优点:代码简单
缺点:单纯的增强for循环不能涉及跟索引相关的操作
*/

//方式3:利用普通for循环: 逆向遍历:
for(int i=9;i>=0;i--){
System.out.println("第"+(i+1)+"个学生的成绩为:"+scores[i]);
}
}
}

用IDEA验证数组的确将数据进行存储

数组的三种初始化
  • 静态初始化:除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值
1
2
3
4
5
6
7
eg:
int[] arr = {12,23,45};
int[] arr = new int[]{12,23,45};
注意:
1.new int[3]{12,23,45};-->错误,不需要再定义长度
2.int[] arr ;
arr = {12,23,45}; --->错误,不能分开写
  • 动态初始化:数组定义与为数组元素分配空间并赋值的操作分开进行
1
2
3
4
5
6
eg:
int[] arr ;
arr = new int[3]
arr[0] = 12;
arr[1] = 23;
arr[2] = 45;
  • 默认初始化:数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
1
int[] arr = new int[3];   ---> 数组有默认的初始化值

数组最值问题

实现一个功能:给定一个数组int[] arr = {12,3,7,4,8,125,9,45}; ,求出数组中最大的数

原理图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TestArray04{
public static void main(String[] args){
//1.给定一个数组
int[] arr = {12,3,7,4,8,125,9,45,666,36};

//2.求出数组中的最大值:
//先找一个数上擂台,假定认为这个数最大:
// 这里 i<arr.length ==> i<10
int maxNum = arr[0];
for(int i=0;i<arr.length;i++){
if(arr[i]>maxNum){
maxNum = arr[i];
}
}
System.out.println("当前数组中最大的数为:"+maxNum);
}
}
将求最大值的方法提取出来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class TestArray04{
public static void main(String[] args){
//实现一个功能:给定一个数组int[] arr = {12,3,7,4,8,125,9,45}; ,求出数组中最大的数。
//1.给定一个数组
int[] arr = {12,3,7,4,8,725,9,45,666,36};

//2.求出数组中的最大值:
//调用方法:
int num = getMaxNum(arr);
System.out.println("当前数组中最大的数为:"+num);
}

/*
想提取一个方法:求数组中的最大值
求哪个数组中的最大值 ---》不确定因素:哪个数组 (形参)---》返回值:最大值
*/
public static int getMaxNum(int[] arr){
//先找一个数上擂台,假定认为这个数最大:
int maxNum = arr[0];
for(int i=0;i<arr.length;i++){
if(arr[i]>maxNum){
maxNum = arr[i];
}
}
return maxNum;
}
}

画内存

方法的实参传递给形参的时候一定要注意:一切都是值传递

  • 如果是基本数据类型,那么传递的就是字面值
  • 如果是引用数据类型,那么传递的就是地址值

数组的查询问题
查询指定位置的元素
1
2
3
4
5
6
7
8
9
public class TestArray05{
public static void main(String[] args){
//查询指定位置的元素
//给定一个数组:
int[] arr = {12,34,56,7,3,10};
//查找索引为2的位置上对应的元素是什么?
System.out.println(arr[2]);
}
}

上面代码体现了数组的一个优点:在按照位置查询的时候,直接一步到位,效率非常高

查询指定元素的位置,找出元素对应的索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TestArray06{
public static void main(String[] args){
//查询指定元素的位置--》找出元素对应的索引
//给定一个数组:
int[] arr = {12,34,56,7,3,56};
// 0 1 2 3 4 5

//功能:查询元素888对应的索引:
int index = -1; //这个初始值只要不是数组的索引即可
for(int i=0;i<arr.length;i++){
if(arr[i]==56){
index = i;//只要找到了元素,那么index就变成为i
break;//只要找到这个元素,循环就停止
}
}
if(index!=-1){
System.out.println("元素对应的索引:"+index);
}else{//index==-1
System.out.println("查无此数!");
}
}
}
将查指定元素对应的索引的功能提取为方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class TestArray06{
public static void main(String[] args){
//查询指定元素的位置--》找出元素对应的索引
//给定一个数组:
int[] arr = {12,34,56,7,3,56};
// 0 1 2 3 4 5

//功能:查询元素888对应的索引:
//调用方法:
int index = getIndex(arr,999);
//后续对index的值进行判断:
if(index!=-1){
System.out.println("元素对应的索引:"+index);
}else{//index==-1
System.out.println("查无次数!");
}
}

/*
定义一个方法:查询数组中指定的元素对应的索引:
不确定因素:哪个数组,哪个指定元素 (形参)
返回值:索引

*/
public static int getIndex(int[] arr,int ele){
int index = -1; //这个初始值只要不是数组的索引即可
for(int i=0;i<arr.length;i++){
if(arr[i]==ele){
index = i;//只要找到了元素,那么index就变成为i
break;//只要找到这个元素,循环就停止
}
}
return index;
}
}
数组添加元素

逻辑图

给定一个数组,在数组下标为2的位置上添加一个元素91
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class TestArray07{
public static void main(String[] args){
//功能:给定一个数组,在数组下标为2的位置上添加一个元素91
//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,55,66,77,88,999,89};
// 0 1 2 3 4 5
//2.输出增加元素前的数组:
System.out.print("增加元素前的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}

//3.增加元素
/*
arr[5] = arr[4];
arr[4] = arr[3];
arr[3] = arr[2];
*/
int index = 1;//在这个指定位置添加 元素
for(int i=arr.length-1;i>=(index+1);i--){
arr[i] = arr[i-1];
}
arr[index] = 666;

//4.输出增加元素后的数组:
System.out.print("\n增加元素后的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}
}
}
将添加功能提取为一个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.util.Scanner;
public class TestArray07{
public static void main(String[] args){
//功能:给定一个数组,在数组下标为2的位置上添加一个元素91
//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,55,66,77,88,999,89};
// 0 1 2 3 4 5
//2.输出增加元素前的数组:
/*
System.out.print("增加元素前的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}
*/

//从键盘接收数据:
Scanner sc = new Scanner(System.in);
System.out.print("请录入你要添加元素的指定下标:");
int index = sc.nextInt();
System.out.print("请录入你要添加的元素:");
int ele = sc.nextInt();

//3.增加元素
//调用方法:
insertEle(arr,index,ele);

//4.输出增加元素后的数组:
System.out.print("\n增加元素后的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}

}


/*
提取一个添加元素的方法:
在数组的指定位置上添加一个指定的元素。
在哪个数组的哪个位置添加哪个元素!
不确定因素:形参:哪个数组,哪个位置,哪个元素
返回值:无

*/
public static void insertEle(int[] arr,int index,int ele){
for(int i=arr.length-1;i>=(index+1);i--){
arr[i] = arr[i-1];
}
arr[index] = ele;
}
}
数组删除元素

逻辑图

删除指定位置上的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.Arrays;
public class TestArray08{
public static void main(String[] args){
//功能:给定一个数组,删除下标为2元素

//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,34,45,56,7,666};
// 0 1 2 3 4 5
//2.输出删除前的数组:
System.out.println("删除元素前的数组:"+Arrays.toString(arr));

//3.删除
/*
arr[2] = arr[3];
arr[3] = arr[4];
arr[4] = arr[5];
*/
int index = 0; //删除下标为0的数 12
for(int i=index;i<=arr.length-2;i++){
arr[i] = arr[i+1];
}
arr[arr.length-1] = 0;

//4.输出删除后的数组:
System.out.println("删除元素后的数组:"+Arrays.toString(arr));
}
}
删除指定元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.Arrays;
public class TestArray09{
public static void main(String[] args){
//功能:给定一个数组,删除元素3

//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,34,45,56,7,666};

//2.输出删除前的数组:
System.out.println("删除元素前的数组:"+Arrays.toString(arr));

//找到要删除的元素对应的索引即可:
int index = -1 ;
for(int i=0;i<arr.length;i++){
if(arr[i]==3){
index = i;
break;
}
}

//3.删除

if(index!=-1){
for(int i=index;i<=arr.length-2;i++){
arr[i] = arr[i+1];
}
arr[arr.length-1] = 0;
}else{//index==-1
System.out.println("根本没有你要删除的元素!");
}

//4.输出删除后的数组:
System.out.println("删除元素后的数组:"+Arrays.toString(arr));
}
}
详解main方法
  1. main方法:程序的入口,在同一个类中,如果有多个方法,那么虚拟机就会识别main方法,从这个方法作为程序的入口
  2. main方法格式严格要求
    • public static void main(String[] args){}
    • public static —>修饰符 ,暂时用这个 –>面向对象一章
    • void —>代表方法没有返回值 对应的类型void
    • main —>见名知意名字
    • String[] args —>形参 —》不确定因素
  3. 问题:程序中是否可以有其他的方法也叫main方法?
    • 可以,构成了方法的重载
1
2
3
4
5
6
7
8
public class TestArray10{
public static void main(String[] args){

}
public static void main(String str){

}
}
  1. 形参为String[] 那么实参到底是什么?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestArray10{
public static void main(String[] args){
//从侧面验证:
//int[] arr1; //如果对数组只声明,没有后续操作,那么相当于 白定义了。
//int[] arr2 = null;
//System.out.println(arr2.length);//Exception in thread "main" java.lang.NullPointerException
//int[] arr3 = new int[0];
//System.out.println(arr3.length);
//int[] arr4 = new int[4];
//System.out.println(arr4.length);

//System.out.println(args.length);//0
//从这个结果证明,参数是String[],实参是 new String[0]
//默认情况下,虚拟机在调用main方法的时候就是传入了一个长度为0的数组
System.out.println(args.length);
for(String str:args){
System.out.println(str);
}
}
}

可变参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class TestArray12{
/*
1.可变参数:作用提供了一个方法,参数的个数是可变的 ,解决了部分方法的重载问题
int...num
double...num
boolean...num

2.可变参数是在JDK1.5之后加入的新特性
3.方法的内部对可变参数的处理跟数组是一样
4.可变参数和其他数据一起作为形参的时候,可变参数一定要放在最后
5.我们自己在写代码的时候,建议不要使用可变参数。
*/
public static void main(String[] args){
//method01(10);
//method01();
//method01(20,30,40);
method01(30,40,50,60,70);
//method01(new int[]{11,22,33,44});
}
public static void method01(int num2,int...num){
System.out.println("-----1");
for(int i:num){
System.out.print(i+"\t");
}
System.out.println();

System.out.println(num2);
}
}
Arrays工具类

为了方便我们对数组进行操作,系统提供一个类Arrays,我们将它当做工具类来使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.Arrays;
public class TestArray13{
public static void main(String[] args){
//给定一个数组:
int[] arr = {1,3,7,2,4,8};
//toString:对数组进行遍历查看的,返回的是一个字符串,这个字符串比较好看
System.out.println(Arrays.toString(arr));

//binarySearch:二分法查找:找出指定数组中的指定元素对应的索引
//这个方法的使用前提:一定要查看的是一个有序的数组:
//sort:排序 -->升序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.binarySearch(arr,4));

int[] arr2 = {1,3,7,2,4,8};
//copyOf:完成数组的复制
int[] newArr = Arrays.copyOf(arr2,4);
System.out.println(Arrays.toString(newArr));

//copyOfRange:区间复制
int[] newArr2 = Arrays.copyOfRange(arr2,1,4);//[1,4)-->1,2,3位置
System.out.println(Arrays.toString(newArr2));

//equals:比较两个数组的值是否一样
int[] arr3 = {1,3,7,2,4,8};
int[] arr4 = {1,3,7,2,4,8};
System.out.println(Arrays.equals(arr3,arr4));//true 比较左右两侧的值是否相等
System.out.println(arr3==arr4);//false 比较的是左右的地址值,返回结果一定是false

//fill:数组的填充,全部都为10
int[] arr5 = {1,3,7,2,4,8};
Arrays.fill(arr5,10);
System.out.println(Arrays.toString(arr5));
}
}
数组的复制操作

System.arraycopy方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Arrays;
public class TestArray14{
public static void main(String[] args){
//给一个源数组:
int[] srcArr = {11,22,33,44,55,66,77,88};
//给一个目标数组:
int[] destArr = new int[10];

//复制:
System.arraycopy(srcArr,1,destArr,3,3);
//遍历查看目标数组:
System.out.println(Arrays.toString(destArr));
}
}

二维数组的定义和遍历
  1. 引入:本质上全部都是一维数组

1
2
3
4
5
6
7
8
9
10
11
public class TestArray15{
public static void main(String[] args){
//定义一个二维数组:
int[][] arr = new int[3][];//本质上定义了一个一维数组,长度为3
int[] a1 = {1,2,3};

arr[0] = a1;
arr[1] = new int[]{4,5,6,7};
arr[2] = new int[]{9,10};
}
}

对应内存

四种遍历方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class TestArray15{
public static void main(String[] args){
//定义一个二维数组:
int[][] arr = new int[3][];//本质上定义了一个一维数组,长度为3
int[] a1 = {1,2,3};
arr[0] = a1;
arr[1] = new int[]{4,5,6,7};
arr[2] = new int[]{9,10};

//读取6这个元素
//System.out.println(arr[1][2]);

//对二维数组遍历
//方式1:外层普通for循环+内层普通for循环
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();
}

//方式2:外层普通for循环+内层增强for循环
for(int i=0;i<arr.length;i++){
for(int num:arr[i]){
System.out.print(num+"\t");
}
System.out.println();
}

//方式3:外层增强for循环+内层增强for循环
for(int[] a:arr){
for(int num:a){
System.out.print(num+"\t");
}
System.out.println();
}

//方式4:外层增强for循环+内层普通for循环
for(int[] a:arr){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
}
}
}
二维数组的初始化方式
  • 静态初始化:除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值
1
2
3
eg:
int[][] arr = {{1,2},{4,5,6},{4,5,6,7,8,9,9}};
int[][] arr =new int[][] {{1,2},{4,5,6},{4,5,6,7,8,9,9}};
  • 动态初始化:数组定义与为数组元素分配空间并赋值的操作分开进行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
eg:
int[][] arr = new int[3][]; //本质上定义了一维数组长度为3,每个“格子”中放入的是一个数组
arr[0] = new int[]{1,2};
arr[1] = new int[]{3,4,5,6};
arr[2] = new int[]{34,45,56};

eg:
int[][] arr = new int[3][2];
public class TestArray16{
public static void main(String[] args){
//本质上:定义一维数组,长度为3,每个数组“格子”中,有一个默认的长度为2的数组
int[][] arr = new int[3][2];

arr[1] = new int[]{1,2,3,4}; // true

//数组遍历:
for(int[] a:arr){
for(int num:a){
System.out.print(num+"\t");
}
System.out.println();
}
}
}
  • 默认初始化:数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化


----------- 本文结束 -----------




Buy me a coffee.