Hello,小伙伴接下来就由我来带领大家进入java的世界:
一,java背景历史:
毕竟作为一名java程序员,以后就是要和别人用java打交道的,所以我们还是要了解一下,java的历史背景的。
1.1 java语言的历史
1. java是哪家公司的产品?
java是美国SunStanford University Network,斯坦福大学网络公司)公司在1995年推出的一门计算机高级编程语言。但是在2009年是Sun公司被Oracle(甲骨文)公司给收购了,所以目前Java语言是Oracle公司所有产品。
2. java名称的来历?
早期这门语言的名字其实不叫Java,当时称为Oak(橡树的意思),为什么叫橡树呢?原因是因为Sun公司的门口种了很多橡树,但是后来由于商标注册时,Oak商标已经其他公司注册了,所以后面改名为Java了。那么有人好奇为什么叫Java呢?Java是印度的一个岛屿,上面盛产咖啡,可能是因为他们公司的程序员喜欢喝咖啡,所以就改名为Java了。
3. java的创始人是谁?
Java的联合创始人有很多,但是行业普遍认可的Java的创始人 是詹姆斯●高斯林,被称为Java之父
1.2 java到底能做什么?
我们已经选择了要学习java,所以还是要知道一下,学习java知识,到底能做些什么。
java能做的事情确实很多,比如:左面应用的开发,企业互联网应用的开发,移动应用开发,服务器系统开发,大数据开发,游戏开发等等。
应用举例:
1,桌面应用的开发:能够在电脑桌面运行的软件
举例:财务管理软件、编写程序用的IDEA开发工具等,可以用Java语言开发
2,企业级应用开发:大型互联网应用程序
举例:淘宝、京东,拼多多
3,移动应用开发:运行的Android手机端软件
举例:QQ,微信,抖音
4,服务器系统:应用系统的后台(为客户端程序提供数据)
举例:服务器系统为用户推荐那你喜爱的视频
5,游戏开发:游戏本质上是给用户提供娱乐的软件,就是用java语言开发的
举例:我的世界MineCraft就是用Java语言开发的
1.3java的技术体系:
主要有三个版本
- javaSE(java Standard Edition):叫做java的标准版,它是后面两个版本的基础。我们在学习java的时候,必须要先学习这个。
- javaEE(java Enterprise Edition):叫做企业版,它是为企业级应用开发提供的一套解决方案。
- javaME(java Micro Edition):叫做java的小型版,为开发移动设备的应用提供了一套解决方案。现在已经不流行了,被Android取而代之。
简单回顾:
1,java是什么?
java是一门高级编程语言
2,Java是哪家公司的产品?
以前是Sun公司,现在是oracle公司
3,java之父是谁?
詹姆斯.高斯林
4,Java主流的开发方向是什么?
企业级互联网应用开发
5,java技术平台有哪些?
JavaSE(标准版)、JavaEE(企业版)、JavaME(小型版)
二,快速入门:
JDk的发展历史:
2.1JDk的下载和安装:
jdk下载连接:
先择JDK21版本,找到window标签,选择x64 install 版本
下载完成之后,会出现jdk的安装包
安装JDK:
jdk安装好之后,不会在页面上出现图标。高版本的jdk会自动配置环境变量,不需要我们自己手动配置。
如何验证jdk是否安装成功呢?
我们找到jdk的安装目录:具体路径根据自己安装的位置为准!!!
在bin目录下,会看到 javac,java这是jdk给我们提供的编译和运行的工具
C:\Program Files\Java\jdk-21\bin
方式一:
①window + r
输入cmd 点击回车
②输入 java
输入 javac
输入java -version 或者 javac -version
如果出现,不是内部或者外部命令,需要配置环境变量。
配置环境变量:
window+e 回车 在此电脑处右击点击属性。
点击:高级系统设置
点击环境变量:
可以看到上面是用户变量,下面是系统变量。用户变量仅仅只能让自己使用,系统变量所有的用户都可以访问。
在系统变量里面找到path
找到path点击编辑:
两个环境变量都配置好了以后,点击确定关闭
三,java开发工具:
用记事本写代码,先生的很是麻烦,有没有一种工具,能够帮助我们快速的将写代码,编译,运行等工具,集成到一起呢?有,这就是集成开发环境(Integrated Development Environment ,简称IDE)。除此之外,IDEA还有代码提示、检查代码错误等功能,从而提高程序员的开发效率。
IDE有很多种,常见的有Eclipse,MyEclipse,intellj iDEA,jBuilder等等
3.1 IDEA下载和安装
找到,idea的安装包,双击,然后一直点击next即可。
3.2IDEA编写java程序:
想要在IDEA正确的写一个java程序,必须先认识一下IDEA的管理java程序的工程结构
- 第一步:首先在IDEA中创建一个project(工程,也叫项目),后面都统称为工程。
- 第二步:需要在project中创建Module(模块),一个工程中可以包含多个模块。
- 第三步:需要在Module中新建package(包),一个模块中可以有多个包。
- 第四步:需要在package中新建class(类),一个包中可以包含多个类。
软件工程其实类似于建筑工程,我们对比建筑工程来理解。
project(工程):可以理解成小区的院子
Module(模块):可以理解成小区院子里面的每一栋楼
Package(包):可以理解成每一栋楼的一层
Class(类):可以理解成每一户的住户
创建project工程:
打开我们心爱的IDEA,点击new project
点击 Empty Project(空项目)
新建Module(模块)
修改模块的名称和位置(按需修改)
新建包:
在刚刚新建好的module里面,新建包
新建类:
在刚刚新建好的包下,右击,new -> java Class
在新建好的类里面,写一些东西,然后运行。
3.4 IDEA的各种配置:
我们可能在使用idea的时候,感觉字体比较小。背景是黑色或者白色,不是自己喜欢的颜色。这个时候,我们是可以手动调节的。
主题配置:
file -> Settings -> Apperance -> 下拉选择Theme(主题)
字体配置:
file -> Settings -> Editor -> Font
背景色配置:
file -> Color Scheme -> General -> Text -> Default text
把背景色的颜色值,调为204、238、200;就是豆沙绿的护眼色了
3.5 常用快捷键:
使用快捷键,可以大大提高我们的开发效率。
快捷键 | 功能效果 |
main/pavm,sout | 快速键入相关代码 |
Ctrl+D | 复制当前行数据到下一行 |
Ctrl + Y | 删除所在行,建议用Ctrl + X |
Ctrl + ALT + L | 格式化代码 |
ALT + SHIFT + ↑ , ALT + SHIFT + ↓ | 上下移动当前代码 |
Ctrl + / , Ctrl + Shift + / | 对代码进行注释(讲注释的时候再说) |
Shift+f6 | 快速替换所有类似项 |
Alt+Enter | 万能键 |
Alt+Insert | 快速构建,构造方法,getter.... |
四,java基础语法:
想要编写java代码,必须学习java代码
4.1 注释
什么是注释?
注释就是解释说明程序的问题,方便自己和别人阅读代码
1.单行注释:
//后面根解释文字
2.多行注释
/*
这里写注释文字
可以写多行
*/
3.文档注释
/**
这里写文档注释
也可以写多行,文档注释可以利用JDK的工具生成帮助文档
*/
示例代码:
/**
目标:学会使用注释
这是程序的讲解注释
*/
public class NoteDemo{
//这是程序的主方法,是程序的入口
public static void main(String[] args){
System.out.println("我开始学习Java程序,好开心~~");
/*
窗前明月光
疑是地上霜
举头望明月
低头思故乡
*/
System.out.println("道恩");
System.out.println("DaoEn");
}
}
4.2字面量:
什么是java字面量?
字面量就是告诉程序员数据在程序中书写的格式。下面我就来列举一些
常用数据 | 生活中的写法 | 程序中的写法 | 说明 |
整数 | 666,888 | 666,888 | 写法是一样的 |
小数 | 13.14 -5.12 | 13.14 ,-5.12 | 写法一样的 |
字符 | A,0 ,中 | 'A' ,'0' , '中' | 程序中必使用单引号,内容可有可无 |
字符串 | 孙道恩帅哥 | "孙道恩帅哥" | 程序中必须使用双引号,内容可有可无 |
布尔值 | 真,假 | true,false | 只有两个值,真:true 假:false |
空值 | 值 null | 一个特殊的值,空值 |
public class LiteralDemo{
public static void main(String[] args){
//1.整数
System.out.println(666);
//2.小数
System.out.println(3.66);
//3.字符: 字符必须用单引号引起来
System.out.println('a');
System.out.println('0');
System.out.println('中');
System.out.println(' '); //空格也算字符
//特殊字符:\t表示制表符 \n表示换行
System.out.println('\t'); //这相当于一个tab键,专业叫做制表符
System.out.println('\n'); //这是换行的意思
//4.字符串:字符串是双引号引起来的
System.out.println("我爱你中国abc");
//5.布尔值:只有两个值true和false
System.out.println(true);
System.out.println(false);
}
}
4.2变量
什么是变量?
变量就是用来记录程序中的数据,其本质上是内存中的一块区域,我们把这块区域理解成一个小盒子。
变量含义的解释:
int age = 20;
System.out.println(age);
当执行 int age = 20;这句代码是,jvm会在内存中申请一块区域,在这个区域中存储了一个整数20,给这个区域取名叫age;相等于在这个盒子中存了一个数据20,这个盒子的名字叫age,我们打印age时,就是从盒子中把盒子中的数据取出来再打印。
变量的声明语法
①一次声明一个变量 数据类型 变量名;
②一次声明多个同类型的变量 数据类型 变量名1,变量名2
③声明的数据类型:byte ,short,int,long ,float ,double ,char,boolean,String ,类,接口
④变量名的命名规范,要遵循标识符的命名规范。
首字母 其后字母
字母_ $ 字母_ $ 数字
变量的赋值语法:
先声明在赋值
int days;
days = 10;
long peopleNum;
peopleNum = 1111111;
声明的时候直接赋值
int age = 21;
为什么使用变量?
使用变量记录数据,对于数据的管理更为灵活。
示例:
//1.假设4多个地方用到整数10; 现在我想把10改为20,这时你得一条语句一条语句的修改
System.out.println(10);
System.out.println(10);
System.out.println(10);
System.out.println(10);
//2.同样这里还是在多个地方用到整数10,你可以先用一个变量记录这个整数10
int x = 10;
//然后在需要用到整数10的地方,用x代替就行;
//如果我们把x值改了,那么后面用到x的值的地方就都一起改变了
System.out.println(x);
System.out.println(x);
System.out.println(x);
System.out.println(x);
变量的应用场景?
变量的应用场景无处不在,只要程序中能发生变化的数据,都可以用变量存储。
例如微信钱包里面的余额,微信昵称,微信的个性签名。都是需要经常修改的。
示例:
//比如:你现在有188.8元,一会要发100元,再收20元。
double money = 188.8;
//发100元
money = money - 100;
//再收20元
money = money + 20;
//再打印money记录的值是多少
System.out.println(money);
//再比如:公交车大人2元,小孩一元,公交车经过2站
//第一站:3个大人1个小孩上车
//第二站:1个大人1个小孩上车,请问一共上了多少人,一共收入多少钱?
//刚开始公交车箱子里没有钱,用money2表示箱子里的钱
int money2 = 0;
//刚开始公交车上也没有人,用count变量表示上车的人数
int count = 0;
//经过两站的人数:第一站3人,第二站1人,总的人数是3+1
count = 3+1;
//经过两站的钱数:
money2 = money2+3*2+1; //经过第一站后
money2 = money2+2+1; //经过第二站后
//打印人数和钱数
System.out.println(count);
System.out.println(money);
使用变量的注意事项
1,变量定义在那个{} 范围内,就只在那个大括号内有效,变量的有效范围称为变量的作用域。
{
int a = 10;
System.out.println(a); //这是是对的
}
System.out.println(a); //这里会出错
2,在同一个作用域内,不能同时出现两个同名的变量。
{
int a = 10;
int b = 20; //这里会报错的
}
3,变量没有赋初始值,不能直接使用。
int a ; //这里仅仅是定义了变量,没有给初始值
System.out.pringln(a); //会报错的
4,变量可以定义在同一行。
int a = 10,b = 20; //a b都是int类型的
变量存储值的大小空间,由数据类型决定。
变量存储位置由变量名决定。
变量声明之后没有赋值,使用会报错。
变量的数据类型决定了,其存储数据的范围。
4.4关键字:
什么是关键字?
关键字是java语言中有特殊含义的单词。比如用int表示整数,用double表示小数,等等。
常用的关键字有哪些?
abstract | assert | boolean | break | byte |
---|---|---|---|---|
case | catch | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
如何区别哪些单词是关键字?
关键字的特点:
1,关键字都是小写的
2,关键字在idea中有特殊颜色标记
4.5 标识符:
使用标识符的目的,就是让我们知道取名字的规则,不能随便瞎取。
标识符的规范:
1,最好是字母,数字,下划线_ ,$组成
2,不能以数字开头
3,不能是java关键字
示例:
1.所有的名字要见名知意,便于自己和别人阅读
举例: class Student{} //一看这个类就知道表示一个学生
int age =10; //一看这个变量就知道表示年龄
2.类名:首字母大写(大驼峰命名)
举例: class Student{}
3.变量名:第二个单词开始首字母大写(小驼峰命名)
举例: double money = 6.88;
double applePrice = 7.5;
二,java数据类型,运算符
1,数据的表示详解
1.1,整数在计算机中存储原理
任何数据在计算机中都是以二进制表示的。什么是二进制?二进制就是一种数据的表示形式,它的特点就是逢2进1.
数据的表示形式除了二进制(逢2进1),八进制(逢8进1),十进制(逢10进1),十六进制(逢10进1)
逢二进一法:
1,二进制中只有 0 和 1 两个数
2,二进制如何表示十进制呢?
1
+ 1
------------
10 这里两个1相加,结果为2,由于而二进制满2进1,所以最后的结果是10
3,二进制如何表示十进制的3呢?
上面我们已经知道二进制10表示十进制的2,那么二进制10+1就表示十进制的3
10
+ 1
-------------
11 十进制对应的二进制就是11
4,二进制如何表示十进制的4呢?
上面我们已经知道二进制11表示十进制的3,那么二进制11+1就表示十进制的4
11
+ 1
------------
100 十进制对应的二进制就是100
5,二进制如何表示十进制的5呢?
100
+ 1
----------------
101
除2取余法:
1,怎么做呢?
答:让十进制数据连续除以2,直到商为0,余数反转
2,举例1:把十进制6转换成二进制
商 余数
6/2 3 0
3/2 1 1
1/2 0 1
把余数反转,6对应的二进制就是110
举例2:把十进制的13,转换成二进制
商 余数
13/2 6 1
6/2 3 0
3/2 1 1
1/2 0 1
把余数反转,13对应的二进制是 1101
计算机的最小存储单元:
比如我们想在计算机上存储一个整数6,转换为二进制110,那么计算机中只存110三位数吗?其实不是的,计算机中最小的存储单元是字节(Byte),一个字节占8位(bit),也就是说,数据不足8位来存储。
字符在计算机中的存储原理:
其实字符并不是直接存储的,而是把每一个字符编位一个整数,存储的是字符对应的二进制形式,。由美国人指定的一套字符和和整数的对应关系表,叫做ASCLL编码表
我们需要注意的是,在ASCll编码表张是不包含汉字的。汉字在其他编码表中。
2,数据类型的详解:
在定义变量时我们是要声明数据类型的,这里的数据类型是用来规定变量存储什么类型的数据。
java中的数据类型整体上,划分为两大类: 基本数据类型,引用数据类型
需要我们注意的是,随便写一个小数或者整数的字面量,它也是有默认的数据类型的。
示例1:
public class TypeDemo {
public static void main(String[] args) {
// 1、整型
byte number = 98;
System.out.println(number);
short number2 = 9000;
int number3 = 12323232; // 默认
// 注意:随便写一个整型字面量,默认是int类型的,73642422442424虽然没有超过long的范围,但是它超过了本身int的范围了。
// 如果希望随便写一个整型字面量是long类型的,需要在其后面加上L/l
long number4 = 73642422442424L;
// 2、浮点型
//注意:
//随便写一个小数字面量,默认当成double类型对待的,
//如果希望这个小数是float类型的,需要在后面加上:F/f
float score1 = 99.5F;
double score2 = 99.8; // 默认定义方案。
// 3、字符型
char ch1 = 'a';
char ch2 = '中';
char ch3 = '国';
// 4、布尔型
boolean b1 = true;
boolean b2 = false;
// 引用数据类型:String.
// String代表的是字符串类型,定义的变量可以用来记住字符串。
String name = "道恩";
System.out.println(name);
}
}
3,数据类型的转换:
3.1 自动类型转换:
什么是自动类型转换?
自动类型转换,就是数据范围小的变量的数据,可以直接赋值给数据范围大的变量
byte b = 12;
int a = a; //这里发生了自动类型转换(把byte类型转换位int类型)
自动类型转换的原理是怎么样的?
答:自动类型转换其本质就是在较小数据类型前面,补了若干个字节
示例2
public class typeVersion{
public static void main(String[] args) {
byte a = 12;
int b = a; // 发生了自动类型转换了
System.out.println(a);
System.out.println(b);
int c = 100; // 4
double d = c;// 8 发生了自动类型转换了
System.out.println(d);
char ch = 'a'; // 'a' 97 => 00000000 01100001
int i = ch; // 发生了自动类型转换了 => 00000000 00000000 00000000 01100001
System.out.println(i);
}
}
表达式的自动类型转换
自动类型转换,还有另外一种形式,就是表达式的自动类型转换。所谓表达式指的是几个变量或者几个数据一起参与运算的式子
如果同一个表达式,出现不同类型的变量或者数据一起运算,这种情况下,运算结果是一个什么数据类型呢?
1,多种数据类型参数运算,其结果以最大的数据类型为准
2,byte,short,char,三种数据类型在和其他数据运算时,都会转换成int类型在参与运算。
示例3:
public class TypeConversionDemo2 {
public static void main(String[] args) {
byte a = 10;
int b = 20;
long c = 30;
long rs = a + b + c;
System.out.println(rs);
double rs2 = a + b + 1.0;
System.out.println(rs2);
byte i = 10;
short j = 30;
int rs3 = i + j;
System.out.println(rs3);
// 面试笔试题: 即使两个byte运算,结果也会提升为int
byte b1 = 110;
byte b2 = 80;
int b3 = b1 + b2;
System.out.println(b3);
}
}
3.2 强制类型转换
强制类型转换,就是强行将范围大的数据,赋值给数据范围小的变量。有可能装不下;就像把大桶水,倒入一个小桶水里面,可能会有溢出的风险。
语法:
目标数据类型 变量名 = (目标数据类型)被转换的数据;
示例:
public class TypeConversionDemo3 {
public static void main(String[] args) {
int a = 20;
byte b = (byte) a; // ALT + ENTER 强制类型转换。
System.out.println(a);
System.out.println(b);
int i = 1500;
byte j = (byte) i;
System.out.println(j);
double d = 99.5;
int m = (int) d; // 强制类型转换
System.out.println(m); // 丢掉小数部分,保留整数部分
}
}
强制类型转换的原理:
其实就是强行把前面几个字节砍掉,但是数据有丢失的风险。
4,运算符:
运算符就是参与运算的符号:java提供的运算符有很多种,可以分为以下几类:
- 基本数据类型
- 自增自减运算符
- 赋值运算符
- 关系运算符
- 逻辑运算符
- 三元运算符
4.1 算术运算符:
我们先从最基本的运算符开始学习,算符运算符有 + - * / % ,其中*表示乘法, /表示除法,5表示取余数
注意事项:
/:两个整数相除,结果也是一个整数
%:表示两个数相除,取余数
+:+号除了用作加法运算,还可以作为连接符。+符号与字符串运算的时候,是用作字符串拼接的。其结果还是一个字符串。
public class OperatorDemo1 {
public static void main(String[] args) {
int a = 10;
int b = 2;
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b); // 20
System.out.println(a / b); // 5
System.out.println(5 / 2); // 2.5 ==> 2
System.out.println(5.0 / 2); // 2.5
int i = 5;
int j = 2;
System.out.println(1.0 * i / j); // 2.5
System.out.println(a % b); // 0
System.out.println(3 % 2); // 1
System.out.println("---------------------------------------");
// 目标2:掌握使用+符号做连接符的情况。
int a2 = 5;
System.out.println("abc" + a2); // "abc5"
System.out.println(a2 + 5); // 10
System.out.println("itheima" + a2 + 'a'); // "itheima5a"
System.out.println(a2 + 'a' + "itheima"); // 102itheima
}
}
3.2 自增自减运算符:
++读作自增,--读作自减。
注意:
自增自减只能最变量进行操作,不能操作字面量。
1,单独使用++ -- 放在变量前面没有区别
int a = 10;
a++; //11
--a; //10
System.out.println(a); //102.混合使用:++或者--放在变量或者前面运算规则稍有不同
//++在后:先做其他事情,再做自增和自减(先用在加)
int a = 10;
int b = a++; //等价于 int b = a; a++;//++在前:先自增或者自减,再做其他运输(先加在用)
int x = 10;
int y = --x; //等价于x--; int y = x;
public class OperatorDemo2 {
public static void main(String[] args) {
int a = 10;
// a++; // a = a + 1
++a;
System.out.println(a); //11
// a--; // a = a - 1
--a;
System.out.println(a); //10
// 自增自减只能操作变量不能操作字面量的,会报错!
//System.out.println(2++);
System.out.println("--------------------------------------");
int i = 10;
int rs = ++i; // 先加后用
System.out.println(rs); //11
System.out.println(i); // 11
int j = 10;
int rs2 = j++; // 先用后加
System.out.println(rs2); //10
System.out.println(j); //11
}
}
3.3赋值运算符:
基本的赋值运算符其实就是 = 号,意思就是把 = 号右边的数据赋值给 = 号左边的数据
int a = 10;将数据10 赋值给左边的变量a
扩展:
示例:
public class OperatorDemo4 {
public static void main(String[] args) {
int a = 10;
int b = 5;
boolean rs = a > b;
System.out.println(rs); //true
System.out.println(a >= b); // 要么a大于b,或者a等于b
System.out.println(2 >= 2); // true
System.out.println(a < b); // false
System.out.println(a <= b); // false
System.out.println(2 <= 2); // true
System.out.println(a == b); // false
System.out.println(5 == 5); // true
// 注意了:判断是否相等一定是用 == ,=是用来赋值的。
// System.out.println(a = b);
System.out.println(a != b); // true
System.out.println(10 != 10); // false
System.out.println(false ^ true ^ false);
}
}
3.5 逻辑运算符:
逻辑运算符是用来将多个条件放在一起运算,最终结果是 true 或者 false
示例:
public class OperatorDemo5 {
public static void main(String[] args) {
// 需求:要求手机必须满足尺寸大于等于6.95,且内存必须大于等于8.
double size = 6.8;
int storage = 16;
// 1、& 前后的条件的结果必须都是true ,结果才是true.
boolean rs = size >= 6.95 & storage >= 8;
System.out.println(rs);
// 需求2:要求手机要么满足尺寸大于等于6.95,要么内存必须大于等于8.
// 2、| 只要多个条件中有一个是true,结果就是true.
boolean rs2 = size >= 6.95 | storage >= 8;
System.out.println(rs2);
// 3、!取反的意思
System.out.println(!true); // false
System.out.println(!false); // true
System.out.println(!(2 > 1)); // false
// 4、^ 前后条件的结果相同时返回false,不同时返回true.
System.out.println(true ^ true); // false
System.out.println(false ^ false); // false
System.out.println(true ^ false); // true
System.out.println(false ^ true); // true
// 5、&& 左边为false,右边不执行。
int i = 10;
int j = 20;
// System.out.println(i > 100 && ++j > 99);
System.out.println(i > 100 & ++j > 99);
System.out.println(j);
// 6、|| 左边是true ,右边就不执行。
int m = 10;
int n = 30;
// System.out.println(m > 3 || ++n > 40);
System.out.println(m > 3 | ++n > 40);
System.out.println(n);
}
}
3.6 三元运算符:
接下来,我们学习一下,三元运算符,什么是三元运算符呢?我们先看一下语法。
关系表达式? 值1 : 值2
三元运算符的执行流程:首先计算表达式的值,如果关系表达式的值位 true,则返回值1;吐过关系表达式的值为false,则返回值2
示例:
public class OperatorDemo {
public static void main(String[] args) {
double score = 58.5;
String rs = score >= 60 ? "成绩及格" : "成绩不及格";
System.out.println(rs); //成绩不合格
// 需求2:找出2个整数中的较大值,并输出。
int a = 99;
int b = 69;
int max = a > b ? a : b;
System.out.println(max); // 99
// 需求3:找3个整数中的较大值。
int i = 10;
int j = 45;
int k = 34;
// 找出2个整数中的较大值。
int temp = i > j ? i : j;
// 找出temp与k中的较大值。
int max2 = temp > k ? temp : k;
System.out.println(max2); 45
//还有另外一种写法,完成三元运算符比较三个值的大小
int max = i > j ? (i > k ? i : k) : (j > k ? j : k);
System.out.println("最大值是:"+max);
}
}
3.7 运算优先级
最后我在给大家介绍一下运算符的优先级,如果想知道各个运算符的优先级。看下图
从图中可知, &&运算符比 ||运算符的优先级高,所以&&和||同时存在时。是先算&& 在算 ||
//这里&&先算 相当于 true || false 结果为true System.out.println(10 > 3 || 10 > 3 && 10 < 3); // true
//有括号先算 相当于 true && false 结果为false System.out.println((10 > 3 || 10 > 3) && 10 < 3); //false
5,案例技术-获取用户键盘输入的数据:
键盘录入这个事情,并不是我们自己做的,而是java本身就提供这样的功能,我们按照它的要求,去调用就行。
使用步骤:
【第1步】:在class类上导包:一般不需要我们自己做,idea工具会自动帮助我们 导包的。
import java.util.Scanner;
【第2步】:得到一个用于键盘扫描器对象(照抄代码就行,固定格式)
//Scanner是键盘扫描器对象(你就把它理解成一个东西),这个东西有录入的功能
//sc是给这个东西取的名字
Scanner sc = new Scanner(System.in);【第3步】:开始调用sc的功能,来接收用户键盘输入的数据。
//sc这个东西有键盘录入整数的功能,这个功能的名字叫nextInt()
//.表示表示调用的意思
int age = sc.nextInt();
System.out.println("我的年龄是:"+age);//sc这个东西还有键盘录入字符串的功能,这个功能的名字叫next
String name = sc.next();
System.out.println("我的姓名是:"+name);
示例:
public class ScannerDemo1 {
public static void main(String[] args) {
// 1、导包:一般不需要我们自己做,idea工具会自动帮助我们 导包的。
// 2、抄写代码:得到一个键盘扫描器对象(东西)
Scanner sc = new Scanner(System.in);
// 3、开始 调用sc的功能,来接收用户键盘输入的数据。
System.out.println("请您输入您的年龄:");
int age = sc.nextInt(); // 执行到这儿,会开始等待用户输入一个整数,直到用户按了回车键,才会拿到数据。
System.out.println("您的年龄是:" + age);
System.out.println("请您输入您的名字:");
String name = sc.next(); // 执行到这儿,会开始等待用户输入一个字符串,直到用户按了回车键,才会拿到数据。
System.out.println(name + "欢迎您进入系统~~");
}
}
三,程序流程控制:
程序的流程控制一般分为三种:顺序结构,分子结构,循环结构
- 顺序结构:就是不加任何控制,代码从main方法开始自上而下执行
- 分支结构:根据条件判断是true还是false,有选择性的执行那些代码。在java语言种提供了两种格式if,switch
- 循环结构:就是控制某一段代码重复执行。在java语言种提供了三种格式,for,while,do-while
分支结构:
1.1 if分支:
if分支有那些格式?
第一种
if(条件表达式){
代码;
}
第二种
if(条件表达式){
代码1;
}else{
代码2
}
第三种
if(条件表达式){
代码1;
}else if(条件表达式){
代码2
}
......
else{
代码n;
}
if的第一种形式:
if的第一种形式执行流程如下:
如果 表达式为 true 就执行下面语句体
如果 条件表达式 为 false 就不执行
示例:
// 需求:测量用户体温,发现体温高于37度就报警。
double t = 36.9;
if(t > 37){
System.out.println("体温异常,不能进入~~");
}
if的第二种形式:
if 第二种形式执行流程如下:
如果 条件表达式 为true 就执行下面的的语句体1
如果 条件表达式 为false 就执行else下面的语句体2
示例:
// 需求2:发红包,你的钱包余额是99元,现在要发出90元
// 如果钱够触发,发红包的动作,如果钱不够,则提示:余额不足。
double money = 19;
if(money >= 90){
System.out.println("红包发送成功了~");
}else {
System.out.println("余额不足~~");
}
if第三种形式:
解读:
if 第三种形式执行流程如下:
如果 条件表达式1 为true,就执行下面的代码1;
如果 条件表达式1 为false,就继续判断条件表达式2;如果 条件表达式2 为true,就执行下面的语句体;
如果 条件表达式2 为false,就继续判断条件语句体3;如果 条件表达式3 为true,就执行下面的语句体3
如果 条件表达式3 为false,就继续判断后面的表达式;....
如果前面所有条件表达式判断都为false,就执行最后的else语句中的代码
示例:
package com.itheima.brahcn;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的温度:");
double t = sc.nextDouble();
if (t > 37){
System.out.println("你的体温异常,拉出去斩了");
}
System.out.println("审查结束");
System.out.println("-------------------------------");
System.out.println("请输入你要发出的红包");
double money = sc.nextDouble();
if (money >= 10){
System.out.println("余额不足,发个屁呀");
}else {
System.out.println("红包发出成功");
}
System.out.println("-------------------------");
System.out.println("请输入该学生的成绩");
double score = sc.nextDouble();
if (score >= 0 && score < 60){
System.out.println("成绩不合格,挂科了");
} else if (score >= 60 && score < 80) {
System.out.println("成绩是一般水平");
} else if (score >= 80 && score < 90) {
System.out.println("成绩良好");
} else if (score >= 90 && score <= 100) {
System.out.println("成绩优秀");
}else {
System.out.println("你输入的成绩异常");
}
System.out.println("------------------------");
if (10 > 5) System.out.println("10 > 5");
}
}
if使用的几个常见问题:
第一个问题:if的()后面不能写分号;否者if下面的语句与if无关
double t = 37.5; if(t > 37);{ //这里多了一个分号 System.out.println("温度异常"); }
第二个问题:if后面的大括号,如果只有一行代码,大括号可以省略
double t = 36.9; if(t > 37) System.out.println("温度异常,隔离");
1.2 switch分支语句:
switch分支的执行流程:
通过比较值,来决定执行那条分支代码。
switch的注意事项:
1,表达式的类型只能是 byte,short,int,char
JDK5开始支持枚举,JDK7开始支持String。 不支持double,float,double
2,case 给出的值不允许重复,且只能是字面量,不能是变量
3,正常使用switch的时候,不要忘记写break,否则会出现穿透现象
演示switch语句匹配的数据类型:
int a = 10;
double b = 0.1;
double b2 = 0.2;
double c = b + b2;
System.out.println(c); //0.300000000004
switch(b){ //b是double类型的不支持会报错
}
演示case后面的值,只能是字面量不能是变量:
int i = 20;
int d = 20;
switch(i){
case 10:
//要执行的代码块
break;
case d: //这里不允许写变量,会报错。
break;
}
演示case穿透现象:
当switch语句中没有遇到break,就会直接穿透到下一个case语句执行,直到遇到break为止。当多个case语句想要执行同一段代码时,可以利用case穿透现象,提高代码复用性。
String week = "周二";
switch (week){
case "周一":
case "周二":
case "周三":
case "周四":
System.out.println("找大佬解决bug");
break;
case "周五":
System.out.println("自己整理文档");
break;
case "周六":
case "周日":
System.out.println("休息时间");
break;
default:
System.out.println("数据异常!!!");
}
循环语句:
for循环
for循环的语法格式:
//for循环格式:
for (初始化语句; 循环条件; 迭代语句) {
循环体语句(重复执行的代码);
}初始化语句:一般是定义一个变量,并给初始值
循环条件:一般是一个关系表达式,结果必须是true或者false
迭代语句:用于对条件进行控制,一般是自增或者自减
循环语句体:需要重复执行的代码
for-循环的执行流程:
为了更直观的理解,我们先写一个案例。
//需求:打印3行Hello World
//i= 0 1 2 3 0<3(成立) 1<3(成立) 2<3(成立) 3<3(不成立)
for(int i = 0; i < 3; i++) {
System.out.println("Hello World");
}
是按照下图的①②③④,②③④...的顺序来执行的。当②条件为true时,再次执行③④代码,然后回到②中继续判断,当②条件为false时,就结束循环。
for循环案例---求和:
案例:求1 - 100 治安所有整数的和
思路:
求和的思路分析:
1)首先需要定义一个求和变量,一般命名为sum
2)再遍历得到所有需要求和的数据(1~100之间的所有整数)
3)让需要求和的数据和sum累加,
结果:所有数据累加完之后最终sum就是所有数据的和
int sum = 0;
//定义一个循环,先产生1-100,这100个数
for (int i = 1; i <= 100; i++) {
//每产生一个数据,就把这个数和sum累加
sum += i; //sum = sum + i;
}
System.out.println("1-100的数据和:" + sum); //5050
for循环案例---求奇数和:
需求: 求 1 - 100之间的奇数和
思路一:
求奇数和的思路(只是求和的数据变成了奇数,思路和前面没有变化)
1)首先需要定义一个求和变量,这里命名为sum1
2)再遍历得到所有需要求和的数据(1~100之间的所有奇数)
3)让需要求和的数据和sum1累加,
结果:所有数据累加完之后最终sum1就是所有数据的和
代码:
//1)定义一个变量用于求和
int sum = 0;
//2)定义一个循环产生1-100之间的奇数
for (int i = 1; i < 100; i+=2) {
// i = 1 3 5 7 ...
//3)让需要求和的数据和sum累加,
sum += i;
}
System.out.println("1-100之间的奇数和:" + sum);
思路二:
求奇数和的思路(只是求和的数据变成了奇数,思路和前面没有变化)
1)首先需要定义一个求和变量,这里命名为sum2
2)再遍历得到所有需要求和的数据(1~100之间的所有整数)
3)在求和之前先对数据判断,如果是奇数,才和sum1累加;否则什么也不干
结果:所有数据累加完之后最终sum1就是所有数据的和
代码:
//1)首先需要定义一个求和变量,这里命名为sum
int sum = 0;
//2)再遍历得到所有需要求和的数据(1~100之间的所有整数)
for (int i = 1; i <= 100; i++) {
if(i % 2 == 1){
sum += i;
}
}
System.out.println("1-100之间的奇数和:" + sum);
while循环:
while循环的格式:
初始化语句
while(循环条件){
循环体语句(被重复执行的代码)
迭代条件
}
while循环的执行流程:
代码的执行流程如下图所示:按照① ②③④ ②③④ ... 的流程执行
如果②步骤为true,才循环执行③④步骤
如果②步骤为false,则循环结束
while循环案例---简单打印:
需求:打印5行hello world
代码:
int i = 0;
while (i < 5) {
System.out.println("Hello World");
i++;
}
while循环案例---折纸案例:
需求:世界最高山峰珠穆朗玛峰高度是:8848.86米=8848860毫米,假如我有一张足够大的它的厚度是0.1毫米。请问:该纸张折叠多少次,可以折成珠穆朗玛峰的高度?
思路:
分析:首先由于不知道折叠多少次,我们可以选择用while循环
1)纸张的初始化厚度为0.1毫米,珠峰的高度为8848860毫米
double peakHeight = 8848860;
double paperThickness = 0.1;
2)每次折叠纸张的厚度为原来的两倍,这是需要循环执行的
while(纸张厚度<8848860){
纸张厚度*=2;
}
3)需要求折叠的次数,可以用一个变量来记录折叠的次数
int 次数 = 0;
while(纸张厚度<8848860){
纸张厚度*=2;
次数++; //每次折叠次数累加
}
结果:等循环结束之后,打印记录次数的值,就是折叠多少次了。
代码:
double peakHeight = 8848860; //定义山峰的高度
double paperThinkess = 0.1; //定义纸张的厚度
int count = 0;
while (paperThinkess < peakHeight){
count ++;
paperThinkess*=2;
}
System.out.println("折叠了"+count+"次");
for,while循环如何选择
- 在功能上来看,for循环能做的,while循环也能做
- 使用规范上来讲:知道循环几次,建议使用for循环;不知道循环几次建议使用while循环
do-while循环:
do-while循环的格式:
初始化语句
do{
循环语句
迭代条件
}while(循环条件)
do-while循环的执行流程:
do-while循环的执行流程,是按照① ②③④ ②③④... 的顺序执行的。
我们会发现,do-while循环的特点是先执行,再判断的。即使条件不成立,也会先执行一次。
do-while循环--简单的循环案例:
需求:打印5行hello world
代码:
int num = 0;
do {
System.out.println("hello world");
num++;
}while (num < 5);
}
死循环:
死循环就是,停不下来的循环。
//for死循环
for(;;){
System.out.println("hello world");
}
//while死循环
while(true){
System.out.println("hello world");
}
//do-while 死循环
do{
System.out.println("hello world");
}while(true);
死循环有什么应用场景呢?
最典型的就是可以用死循环来做服务器程序,比如腾讯的服务器就是一直运行的。随时都可以使用腾讯的产品。
嵌套循环:
嵌套循环就是一个循环中又嵌套另一个循环(就是同学们常说的)
循环嵌套执行流程:外部循环每循环一次,内部循环会全部执行完一轮。
需求:打印三行5列的*
代码:
for (int i = 0; i <3 ; i++) {
for (int j = 0; j <5 ; j++) {
System.out.print("*");
}
System.out.println("");
}
跳转语句,break和continue
前面我们学习了循环结构,在中间我们还接触了死循环的一些形式,那么我想要在循环过程中提前跳出循环怎么做呢?
break作用:跳出并结束当前所在循环的执行
continue作用:结束本次循环,进入下一次循环
案例--演示break的使用,终止循环
需求:吃到第三碗就吃饱了,停止循环。
代码:
for (int i = 1; i <= 5 ; i++) {
System.out.println("我吃了第"+i +"碗饺子");
if (i == 3){
break;
}
}
案例--演示continue的使用,结束循环中的一次,继续下一次循环。
代码:
// 2、continue:跳出当前循环的当次执行,直接进入循环的下一次执行。
// 场景: 星期三请假,没有去上班。
//
for (int i = 1; i <= 5; i++) {
if(i == 3) {
// 已经到了第三天,请假了,不用上班。
continue;
}
System.out.println("上班:" + i);
}
break和continue的区别:
- break:只能用于结束所在循环,或者结束所在switch分支的执行。
- cintinue:只能在循环中使用
循环结构的总结:
1,什么是流程控制:
流程控制是用来控制程序的执行顺序的
2,分支结构if和switch,如何选择?
if分支:一般用于对一个范围进行判断
switch分支:对一个一个值进行匹配3,for循环和shile循环,do-while循环如何使用?
知道循环次数用for循环,不知道循环次数用while循环,想要先执行在判断,用do-while
生成随机数:
如何产生一个随机数:
生成随机数的功能,其实java已经给我们提供了,在JDK中提供了一个类叫Random,我们之只需要调用Random这个类提供的功能就可以了。
注意:
nextInt(n) 功能只能生成: 0 至 n - 1 之间的随机数,不包含n
代码:
// 1、导包。import java.util.Random; (idea会自动完成)
import java.util.Random;
public class RandomDemo {
public static void main(String[] args) {
// 2、创建一个Random对象,用于生成随机数。
Random r = new Random();
// 3、调用Random提供的功能:nextInt得到随机数。
for (int i = 1; i <= 20; i++) {
int data = r.nextInt(10); // 0 - 9
System.out.println(data);
}
}
}
猜数字小游戏:
需求:随机生成一个 1 - 100之间的随机数,提示用户猜测,猜大了,提示猜大了,猜小了提示猜小了,直到猜对游戏结束。
代码:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Random r = new Random();
int number = r.nextInt(100)+1;
while (true){
System.out.println("请输入你要猜的数字:");
int guessNum = sc.nextInt();
if (guessNum > number){
System.out.println("猜大了");
} else if (guessNum < number) {
System.out.println("猜小了");
}else {
System.out.println("恭喜你猜对了");
}
}
}
java数组:
一,认识数组:
1,什么是数组:
数组就是一个容器,用来存放一批同种类型的数据
比如我们想要存储 20,10,43,65,76 这些数据,我们可以把代码这样写。
int[] arr = {20,10,43,65,76};
比如我们想要存储张三,李四,王二这些数据。我们可以这样写。
String[] str = {"张三","李四","王二"};
2,数组的应用场景:
有变量的存在了,为什么我们还需要定义数组。比如我们需要定义一个点名器。
用变量来做的化,就显得很繁琐。
我们可以用用数组来替换变量,这样做写法更加简介。
public static void main(String[] args) {
String[] names = {"张三","李四","王二", ......,"李哈哈","孙尚香"};
//假设我们定义了,70个学生,这样直接运行会报错,因为实际上我没有写出70个学生
Random r = new Random();
int i = r.nextInt(70);
System.out.println(names[i]+":回答问题");
}
二,数组的定义和访问:
数组有两种初始化的方式:
- 静态初始化
- 动态初始化
2.1 数组静态初始化:
所谓静态初始化,就是在定义数组的时候直接给数组中的元素赋值
静态初始化的标准格式:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,.....};
按照格式定义int类型和double类型
//定义数组,用来存储多个年龄
int[] ages = new int[]{12, 24, 36}
//定义数组,用来存储多个成绩
double[] scores = new double[]{89.9, 99.5, 59.5, 88.0};
静态初始化的简化写法:
数据类型[] 数据名 = {元素1,元素2,元素3,.....};
按照格式定义int类型的数组和double类型的数组:
//定义数组,用来存储多个年龄
int[] ages = {12, 24, 36}
//定义数组,用来存储多个成绩
double[] scores = {89.9, 99.5, 59.5, 88.0};
注意事项:
定义数组的时候,数据类型[] 数名 也可以写成 数据类型 数组名[]
示例:
//以下两种写法是等价的。但是建议大家用第一种,因为这种写法更加普遍
int[] ages = {12, 24, 36};
int ages[] = {12, 24, 36}
数组在计算机中基本原理:
我们以int[] ages = {12,24,36};这句为例,看一下这句话到底在计算机中做了那些事。
- 首先,左边int[] ages 表示定义了一个数组类型的变量,变量名叫ages
- 其次,右边{12,24,36} b表示创建了一个数组对象,我们完全可以理解成一个能装数据的东西。这和对象在内存中会有一个地址值。[I@4c89990,每创建一个数组对象有一个地址值。
- 然后,把右边的地址值,[I@4c89990,赋值欸左边的agrs变量。
- 所以,ages变量就可以通过地址值,找到数组这个对象(东西)
2.2数组的元素访问:
刚刚我们已经学习了,数组就是用来存储数据的,那么存在数组中的数据又是如何访问的呢?意思就是获取数组元素里面的值或者给数组中的元素赋值。
数组中存储的数据我们叫做元素;而数组中的每一个元素都有一个编号与之对应,我们把这个编号叫做索引。这个索引就是从0开始的依次递增的整数。
要想访问数组中的元素,格式如下:
//数组名可以找到数组对象的地址,在通过索引就可以定位到具体的元素了。
数组名[索引]
代码演示:
//索引: 0 1 2
int[] arr = {12, 24, 36};
// 1、访问数组的全部数据
System.out.println(arr[0]); //12
System.out.println(arr[1]); //24
System.out.println(arr[2]); //36
//下面代码没有3索引,会出现ArrayIndexOutOfBoundsException 索引越界异常
//System.out.println(arr[3]);
// 2、修改数组中的数据
arr[0] = 66;
arr[2] = 100;
System.out.println(arr[0]); //66
System.out.println(arr[1]); 0
System.out.println(arr[2]); //100
除了访问数组中的元素,我们获取数组中元素的个数,后面统称为数组的长度。
// 3、访问数组的元素个数:数组名.length
System.out.println(arr.length);
// 技巧:获取数组的最大索引: arr.length - 1(前提是数组中存在数据)
System.out.println(arr.length - 1);
int[] arr2 = {};
System.out.println(arr2.length - 1);
2.3数组元素的遍历:
所谓的数组遍历就是把数组中的元素一个一个取出来
代码:
int[] ages = {12, 24, 36};
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
要是数组中的元素有很多个,我们一个一个遍历,显得很麻烦。我们可以使用循环遍历数组
我们使用for循环从0开始一直比哪里到长度 - 1的位置,就可以获取到数组中的所有索引。
int[] arr = new int[]{12,32,54,65,34};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
数组静态初始化案例:
需求:某部门5名员工的销售额分别是:16、26、36、6、100,请计算出他们部门的总销售额。
public static void main(String[] args) {
int[] arr = {16,26,36,6,100};
int sum = 0;
for (int i = 0; i <arr.length ; i++) {
sum+=arr[i];
}
System.out.println("销售部门的总的营业额是:"+sum);
}
数组的动态初始化:
前面我们,直接在定义的时候就给数组里面的元素赋值,称为静态初始化,还有一种数组赋值的方法,我们叫做动态初始化。
动态初始化不需要我们写出具体的元素,而是指定元素的类型和长度就行。
格式:
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[5];
注意:
数组的动态初始化案例
需求:某歌唱比赛,需要开发一个系统:可以录入6名评委的打分,录入完毕后立即输出平均分做
选手得分
代码:
public static void main(String[] args) {
double avg = getAvg();
System.out.println(avg);
}
/**
* 计算平均分
* @return
*/
public static double getAvg(){
int avg = 0;
int sum = 0;
Scanner sc = new Scanner(System.in);
double[] arr = new double[6];
//录入成绩
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第"+(i + 1)+"位评委的打分:");
double score = sc.nextDouble();
arr[i] = score;
}
System.out.println("动态赋值后的数组:"+arr[0]);
//累加
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
//求平均值
avg = sum / arr.length;
System.out.println("平均分:"+avg);
return avg;
}
三 数组在计算机中的执行原理:
3.1 数组的执行原理,java程序的执行原理。
通过以下代码讲解变量,数组的执行原理。
public class ArrayDemo {
public static void main(String[] args) {
int a = 10;
System.out.println(a);
int[] arr = new int[]{11, 22, 33};
System.out.println(arr);
System.out.println(arr[1]);
arr[0] = 44;
arr[1] = 55;
arr[2] = 66;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
前面我们已经说过,程序在内存中执行的。实际上java程序编译后字节码问及那加载到java虚拟机中执行。
java为了编译虚拟机执行java程序,将虚拟机中的内存分为,方法区,栈,堆。本地方法栈,寄存器 这5块区域。我们重点关注的就是 方法区,栈,堆。
- 方法区:字节码文件先加载到这里
- 栈:方法运行时所进入的内存区域,由于变量在方法中,所以变量也在这一块区域中。
- 堆:存储new出来的东西,并分配地址。由于数组是new出来的,所以数组也在这块区域。
下面的案例执行的内存原理如下图,按照①②③④⑤⑥标记顺序来看。
总结一下,int a = 10 与 int [] arr = new int[]{11,22,33}的区别
- a是一个变量,在栈内存中,a变量中存储的数据就是10这个值
- arr也是一个变量,在栈中,存储的是数组对象在堆内存中的地址值
// 这里的int a是一个基本类型变量,存储的是一个数值
int a = 10 ;
//这里的int[] arr是一个引用类型的变量,存储的是一个地址值
int[] arr = new int[]{44,55,66};
3.2 多变量指向同一个数组的问题:
我们已经了解了数组在内存中的执行原理。我们知道数组类型的变量指向的是堆内存中数组对象的地址。但是在实际开发中可能存在一种特殊情况,就是多变量指向同一个数组对象的形式。
public class ArrayDemo{
public static void main(String[] args) {
// 目标:认识多个变量指向同一个数组对象的形式,并掌握其注意事项。
int[] arr1 = {11, 22, 33};
// 把int类型的数组变量arr1赋值给int类型的数组变量arr2
int[] arr2 = arr1;
System.out.println(arr1); //输出的是地址
System.out.println(arr2); //输出的是地址
arr2[1] = 99; //通过arr2改变数组中的第二个值 变为99
System.out.println(arr1[1]); //通过arr1取出第二个数据 99
arr2 = null; // 拿到的数组变量中存储的值是null
System.out.println(arr2); //报错 notPointerException 空指针异常
//System.out.println(arr2[0]);
//System.out.println(arr2.length);
}
}
在这里我们重点关注一下这段代码:
这里记录的arr1是数组的地址
int [] arr1 = {11,22,33};
//把iint类型二点数组变量arr1赋值给int类型的数组变量arr2
int arr2 = arr1; //把arr1记录的地址值赋值给arr2
此时 arr1和arr2就是同一个地址值
总结一下:
- 两个变量指向同一个数组是,两个变量记录的是同一个地址值
- 当一个变量修改数组中的元素时,另一个变量去访问数组中的元素,元素已经被修改过了。
四 数组的专项练习:
4.1 求最大值:
需求:定义一个int类型数组,求数组中元素的最大值,并打印最大值
思路:1)先找出数组中0索引的元素,假设为最大值,用max表示【擂主】
2)遍历后面的每一个元素和max比较,把较大的元素值重新赋值给max(擂主换人)
3)最后max就是所有元素的最大值(最后站在台上的擂主)
代码实现:
public class Test1 {
public static void main(String[] args) {
int[] score= {100, 340, 543, 323, 435, -5};
// 2、定义一个变量用于最终记住最大值。
int max = faceScores[0];
// 3、从数组的第二个位置开始遍历。
for (int i = 1; i < faceScores.length; i++) {
// i = 1 2 3 4 5
// 判断一下当前遍历的这个数据,是否大于最大值变量max存储的数据,
//如果大于,当前遍历的数据需要赋值给max
if(faceScores[i] > max ){
max = faceScores[i];
}
}
System.out.println("最高分是:" + max);
}
}
4.2素组反转:
需求:某个数组有5个数据:10,20,30,40,50,请将这个数组中的数据进行反转。
[10, 20, 30, 40, 50] 反转后 [50, 40, 30, 20, 10]
思路:1.每次交换,需要有左右两边的两个索引,我们可以用i和j表示
刚开始i=0,j=数组长度-1;
2.每次让i和j索引位置的两个元素互换位置
arr[i]和arr[j]互换位置
3.每次还完位置之后,让i往右移动一位,让j往前移动一位
代码实现:
public class Test2 {
public static void main(String[] args) {
// 1、准备一个数组
int[] arr = {10, 20, 30, 40, 50};
// 2、定义一个循环,设计2个变量,一个在前,一个在后
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
// arr[i] arr[j]
// 交换
// 1、定义一个临时变量记住后一个位置处的值
int temp = arr[j];
// 2、把前一个位置处的值赋值给后一个位置了
arr[j] = arr[i];
// 3、把临时变量中记住的后一个位置处的值赋值给前一个位置处
arr[i] = temp;
}
// 3、遍历数组中的每个数据,看是否反转成功了
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
4.3随机点名:
需求:某公司开发部5名开发人员,要进行项目进展汇报演讲,现在采取随机排名后进行汇报。请先依次录入5名员工的工号,然后展示出一组随机的排名顺序
思路:1.在程序中录入5名员工的工号存储起来 ---> 使用动态初始化数组的方式。
2.依次遍历数组中的每个数据。
3.每遍历到一个数据,都随机一个索引值出来,让当前数据与该索引位置处的数据进行交换。
代码实现:
public class Test3 {
public static void main(String[] args) {
// 1、定义一个动态初始化的数组用于存储5名员工的工号
int[] codes = new int[5];
// 2、提示用户录入5名员工的工号。
Scanner sc = new Scanner(System.in);
for (int i = 0; i < codes.length; i++) {
// i = 0 1 2 3 4
System.out.println("请您输入第" + (i + 1) +"个员工的工号:");
int code = sc.nextInt();
codes[i] = code;
}
// 3、打乱数组中的元素顺序。
// [12, 33, 54, 26, 8]
// i index
Random r = new Random();
for (int i = 0; i < codes.length; i++) {
// codes[i]
// 每遍历到一个数据,都随机一个数组索引范围内的值。
//然后让当前遍历的数据与该索引位置处的值交换。
int index = r.nextInt(codes.length); // 0 - 4
// 定义一个临时变量记住index位置处的值
int temp = codes[index];
// 把i位置处的值赋值给index位置处
codes[index] = codes[i];
// 把index位置原来的值赋值给i位置处
codes[i] = temp;
}
// 4、遍历数组中的工号输出即可
for (int i = 0; i < codes.length; i++) {
System.out.print(codes[i] + " ");
}
}
}
五,Debug调式工具:
为了更好的理解代码的执行流程,这里给大家提供一个在开发中非常重要的用具---Debug调试工具
使用步骤:
第一步:打断点,如下图的红色小圆点
第二步:右键Debug方式启动程序,如下图右键菜单
启动后,代码会停留在打断点的这一行
第三步:点击箭头按钮,一行一行往下执行
java方法:
一,方法的概述:
1.1什么是方法?
方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用。这句话什么意思呢?意思是,把一段功能代码围在一起,别人都可以来调用它。
方法的完整格式:
修饰符 返回值类型 方法名(形参列表){
方法体(需要执行的代码)
return 返回值;
}
我们来看一个简单的需求:比如小明和小李二人,都需要求两个整数的和,不使用代码,写法如下。
// 1、小明
int a = 10;
int b = 20;
int c = a+b;
System.out.println("和是:" + c);
// 2、小李
int a1 = 10;
int b1 = 20;
int c1 = a1+b1;
System.out.println("和是:" + c1);
通过观察不难发现,两次求和的代码中,除了求和的数据不一样,代码组织结构完全一样。
像这种做相同的事情的代码,就可以用方法方法进行封装。需要用到这段代码功能时,让别人调用方法就行。
public class MethodDemo {
public static void main(String[] args) {
// 需求:假如现在很多程序员都要进行2个整数求和的操作。
// 1、小明
int rs = sum(10, 20);
System.out.println("和是:" + rs);
// 2、小李
int rs2 = sum(30, 20);
System.out.println("和是:" + rs2);
}
public static int sum(int a,int b) {
int c = a + b;
return c;
}
}
1.2方法的执行流程:
当调用一个方法时,执行流程,按照下图标注的序号执行。
①通过sum方法名找到sum方法
②把10传递给方法中的参数a
③把20传递给方法中的参数b
④执行方法中的代码,此时 int c = a + b;相当于int c = 10+20;c的值为30;
return c的含义是,把c的结果返回给调用处,也就是sum方法的结果为30
1.3 方法定义的注意点:
- 方法的修饰符;我们暂时都使用public static 修饰(目前看做是固定写法,后面是可以改动的)
- 方法申明了具体的返回值类型,内部必须使用return返回对应的数据
- 形参列表可以有多个,甚至可以没有;如果有多个形参,多个习惯惨必须用,隔开。并且不能给初始化值。
1.4 使用方法的好处:
提高代码复用性,提高开发效率
让程序逻辑更清晰
总结一下:
1.什么是方法?
方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用
2.方法的完整格式是什么样的?
//格式如下:
修饰符 返回值类型 方法名( 形参列表 ){
方法体代码(需要执行的功能代码)
return 返回值;
}
3.方法要执行必须怎么办?
必须调用才执行;
//调用格式:
方法名(...);4.使用方法有什么好处?
提高代码的复用性,提高开发效率,使程序逻辑更清晰。
二,方法的其他形式:
实际设计一个合理的方法,我们需要重点关注下面两点:
- 方法是否需要接收数据处理(是否有参数)
- 方法是否需要返回数据(是否带返回值)
设计一个合理的方法的原则如下:
如果方法不需要返回数据,返回值类型必须申明成void(无返回值申明), 此时方法内部不可以使用return返回数据。
方法如果不需要接收外部传递进来的数据,则不需要定义形参,且调用方法时也不可以传数据给方法。
没有参数,且没有返回值类型(void)的方法,称为值无参数、无返回值方法。此时调用方法时不能传递数据给方法。
需求1:写一个方法,打印3个 hello world
在方法中直接循环3次,就可以完成这个需求。不需要外部方法传递数据,所以不带参数。
public static void main(String[] args) {
//调用方法时,使用方法名()就可以了
printArr();
}
public static void printArr(){
for (int i = 0; i < 3; i++) {
System.out.println("hello world");
}
}
需求2:写一个方法,打印若干个 hello world 具体多少个,由调用者指定。
public static void main(String[] args) {
print(10); //方法不调用是不会执行的,我们在这里调用
}
public static void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("hello world~");
}
}
三,方法使用常见的问题:
- 1. 方法在类种没有先后顺序,但是不能把一个方法定义在另一个方法中。
- 2. 方法的返回值类型写void(无返回申明)时,方法内不能使用return返回数据,
如果方法的返回值类型写了具体类型,方法内部则必须使用return返回对应类型的数据。- 3. return语句的下面,不能编写代码,属于无效的代码,执行不到这儿。
- 4. 方法不调用就不会执行, 调用方法时,传给方法的数据,必须严格匹配方法的参数情况。
- 5. 调用有返回值的方法,有3种方式:
① 可以定义变量接收结果
② 或者直接输出调用,
③ 甚至直接调用;- 6. 调用无返回值的方法,只有1种方式: 只能直接调用。
四,方法的案例:
4.1 方法案例1
需求:计算 1 - n的和
public static void main(String[] args) {
geSum(100);
}
public static int geSum(int n){
int sum = 0;
for (int i = 0; i < n; i++) {
sum+=i;
}
return sum;
}
4.2 方法案例2
需求:判断一个数是奇数还是偶数:
public static void main(String[] args) {
check(10);
check(33);
}
public static void check(int number){
if (number % 2 == 0){
System.out.println(number+"是偶数");
}else {
System.out.println(number+"是奇数");
}
}
五,方法在计算机中的执行原理。
我们知道java程序的运行都是在内存中执行的,而内存区域又分为栈,堆和方法区。那java的方法是在那个内存区域中执行呢?
答案是栈内存。每次调用方法,方法都会进栈执行;执行完后,又会出栈。
假设在main方法中一次调用A方法,B方法,C方法,在内存中的执行流程如下。
- 每次调用放完,方法都会从栈顶压栈执行
- 每个方法执行完后,会从栈顶弹栈出去
5.1 与返回值的方法,内存分析。
public class MethodDemo {
public static void main(String[] args) {
int rs = sum(10, 20);
System.out.println(rs);
}
public static int sum(int a, int b ){
int c = a + b;
return c;
}
}
5. 2 无返回值的方法,内存分析
下面分析一下一个无返回值,无参数的内存原理:
public class Demo2Method {
public static void main(String[] args) {
study();
}
public static void study(){
eat();
System.out.println("学习");
sleep();
}
public static void eat(){
System.out.println("吃饭");
}
public static void sleep(){
System.out.println("睡觉");
}
}
分析:
总结一下:
1,方法的运行区域在哪里?
栈内存
2,栈有什么特点?方法为什么要在栈中运行自己?
先进后出。保证一个方法调用完另一个方法后,可以回来继续执行。
六,方法参数的传递机制
我们刚才演示的一些方法中传递的参数都是基本类型,实际上参数还可以是传递引用类型。接下来,学习一下当参数是基本类型时、和参数是引用类型时的区别。
先记住一个结论:java的参数传递机制都是:值传递
所谓的值传递:指的是传递实参给方法的形参的时候,传递的是实参变量中存储的值的副本。什么是形参?什么是实参?
6.1 参数传递的基本数据类型
java传递参数的机制都是:值传递,传递的是实际存储的值的副本。
6.2 参数传递的是引用数据类型
我们发现,调用change方法是参数是引用数据类型,实际上也是值传递,只不过参数传递存储的地址值。此时change方法和main方法中两个方法中各自有一个变量arrs,这两个变量记录的是同一个地址值[I@4c898043,change方法把数组中的元素改变了,main方法在访问时,元素已经被修改了。
总结一下:
1.基本类型和引用类型的参数在传递的时候有什么不同?
= 都是值传递
- 基本类型的参数传递存储的数据值。
- 引用类型的参数传递存储的地址值。
七,方法参数传递案例:
7.1 方法参数传递案例1
需求:输出一个int类型的数组内容,要求输出格式为:[11, 22, 33, 44, 55]。
public static void main(String[] args) {
int[] arr = {12,43,65,87,42,97};
printArr(arr);
}
public static void printArr(int[] arr){
if (arr == null){
System.out.println("空数组:"+arr);
return;
}
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1){
System.out.print(arr[i]);
}else {
System.out.print(arr[i]+",");
}
}
System.out.println("]");
}
7.2 方法参数传递案例:
需求:比较两个int类型的数组是否一样,返回true或者false
public static void main(String[] args) {
int[] arr1 = {10,20,30};
int[] arr2 = {10,20,30};
System.out.println(equalsArr(arr1, arr2));
}
public static Boolean equalsArr(int[] arr1,int[] arr2){
//当两个数组都为空,相等返回true
if (arr1 == null && arr2 == null){
return true;
}
//当两个数组中有一个是null,就不相等返回false
if (arr1 == null || arr2 == null){
return false;
}
//当两个数组中的元素个数不相等,返回false
if (arr1.length != arr2.length){
return false;
}
//循环遍历判断里面的元素是否相等
for (int i = 0; i <arr1.length ; i++) {
if (arr1[i] == arr2[i]){
return true;
}else {
return false;
}
}
return false;
}
八,方法的重载
所谓方法的重载指的是:一个类中,出现多个相同名字的方法,但是它们的形参列表是不同的,那么这写方法就称为方法的重载。
public class MethodOverLoadDemo1 {
public static void main(String[] args) {
test();
test(100);
}
public static void test(){
System.out.println("===test1===");
}
public static void test(int a){
System.out.println("===test2===" + a);
}
void test(double a){
}
void test(double a, int b){
}
void test(int b, double a){
}
int test(int a, int b){
return a + b;
}
}
重载代码:
public static void main(String[] args) {
eat();
eat("面条");
eat("下午","米饭");
eat("晚上",2,"面条");
}
public static void eat(){
System.out.println("今天中午吃一碗米饭");
}
public static void eat(String eatName){
System.out.println("今天中午吃一碗"+eatName);
}
public static void eat(String eatTime,String eatName){
System.out.println("今天"+eatTime+"一碗"+eatName);
}
public static void eat(String eatTime,int num,String eatName){
System.out.println("今天"+eatTime+"吃"+num+"碗"+eatName);
}
总结一下:
- 什么是方法的重载:
在一个类中,多个方法的名字相同,但它们的形参列表不同。
- 方法重载需要注意什么?
一个类中,只要一些方法的名称相同,形参列表不同,那么它们就是方法的重载了。其他的都不管(修饰符,返回值类型是否一样无所谓)形参列表不同值得是:形参的个数,类型,顺序不同,不关心形参的名称。
九,return单独使用
示例:下面的方法中,当除数为0时,就提前结束方法的执行。
public class Test {
public static void main(String[] args) {
System.out.println("开始");
chu(10 , 0);
System.out.println("结束");
}
public static void chu(int a , int b){
if(b == 0){
return; // 直接跳出并结束当前chu方法的执行
}
int c = a / b;
System.out.println("除法结果是:"+c);
}
}
第一题:发红包案例:
题目: 编写一个Java程序,模拟随机分发红包的过程。(可不用定义方法解决)
要求:
用户输入总金额和红包个数。
使用随机数生成红包金额,确保每个人至少分到1分钱。
依次输出每个红包的金额(注意:要确所有红包的金额和等于总金额
代码:
package com.itheima.demo2;
import java.util.Random;
import java.util.Scanner;
/**
* **题目:** 编写一个Java程序,模拟随机分发红包的过程。(**可不用定义方法解决**)
* 要求:
* - 用户输入总金额和红包个数。
* - 使用随机数生成红包金额,确保每个人至少分到1分钱。
* - 依次输出每个红包的金额(**注意:要确所有红包的金额和等于总金额**)
*/
public class Test2 {
public static void main(String[] args) {
getRedPage();
}
public static void getRedPage(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要发送的红包金额:");
double totalMoney = sc.nextDouble();
//把(元)转换成(分)
totalMoney *= 100;
int redNum;
while (true) {
System.out.println("请输入红包个数:");
redNum = sc.nextInt();
//在保证每人至少一分的情况下判断要发的红包个数是否大于,红包的金额划分的个数
if (redNum > totalMoney){
System.out.println("红包发送量"+totalMoney+"大于你的红包金额划分的数量");
}else {
break;
}
}
//先保证每个人至少能有一分钱的红包(减去输入要发送红包的个数的一分钱之后,在进行抢红包)
totalMoney -= redNum;
Random r = new Random();
//如果1元红包,分给100个人则正好每个人是0.01元
for (int i = 1; i <= redNum; i++) {
if (totalMoney == 0){
System.out.println("第" + (i + 1) + "个人的红包是:0.01");
continue;
}
if (i == redNum){
System.out.println("第"+(i + 1)+"个人抢到的红包是"+(totalMoney+1)/100.0);
break;
}
int currentMoney = r.nextInt((int) totalMoney)+1;
System.out.println(currentMoney);
System.out.println("第"+(i + 1)+"个人抢到了"+(currentMoney+1)/100.0+"元");
totalMoney-=currentMoney;
}
}
}
第二题:特殊数字查找:
题目: 编写一个Java程序,查找满足以下条件的特殊数字(可不用定义方法解决)
要求:
特殊数字是一个四位数,各位数字之和等于12,且百位数字和个位数字相等。
要求输出每个特殊数字。
最终还要统计特殊数字的总个数并输出。
代码:
public class Test1 {
public static void main(String[] args) {
int count = 0;
for (int i = 1000; i <= 9999 ; i++) {
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 100 % 10;
int qian = i / 1000;
if (((ge + shi + bai + qian) == 12) && (bai == ge)){
System.out.println(i);
count++;
}
}
System.out.println("特殊字符的个数:"+count);
}
}
第三题:生成密码:
题目: 编写一个Java程序,生成一个指定长度的密码并返回,比如返回一个密码长度为8的密码(需要设计方法来解决本需求)
要求:
随机的密码可以包含数字、大写字母和小写字母。
需要在main方法中调用自己写的方法验证是否正确
代码:
public class Test33 {
public static void main(String[] args) {
System.out.println(createPwd(5));
System.out.println(createPwd(10));
}
public static String createPwd(int n){
Random r = new Random();
String pwd = "";
for (int i = 0; i < n; i++) {
int index = r.nextInt(3); //如果index的下标 是 0 表示该次添加的是数字,如果下标是 1 表示该次添加的是 小写字母 2 表示 大写字母
switch (index){
case 0:
pwd+= r.nextInt(10);
break;
case 1:
char BigNum = (char) (r.nextInt(26)+65); //大写字母在Ascll表中,65表示的是A 往后推25个 就到了大写字母Z
pwd+=BigNum;
break;
case 2:
char smallNum = (char) (r.nextInt(26)+97); //小写字母在Ascll表中,97表示的是a 往后推25个 就到了小写字母z
pwd+=smallNum;
break;
}
}
return pwd;
}
}
第四题:查找特定元素
题目: 定义一个方法,方法可以接收一个数组和一个整数。方法中实现:判断传递过来的整数是否存在数组中,如果存在,则返回这个整数在数组中的索引,如果不存在,则返回-1。(需要设计方法来解决本需求)
要求:
整型数组和要查找的元素需要自己给出。
需要在main方法中调用自己写的方法验证是否正确。
public class Test4 {
public static void main(String[] args) {
int[] checkArr = {12,34,56,87,88,34,21,45,42,21,65,43};
int checkNum = 10;
System.out.println(checkArrArgsIsExists(checkArr, checkNum));
}
/**
* 检查传递过来的数据是否在数组中
* @param arr
* @param num
* @return
*/
public static int checkArrArgsIsExists(int[] arr,int num){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == num){
return i;
}else {
return -1;
}
}
return 0;
}
}
第五题:随机发出红包
题目:某网红每次直播都会设置6个红包,每个红包的大小是1-100元之间的整数,请开发一个方法,方法内可以录入6个红包,然后该方法内部需要立即模拟输出6个红包发出去的顺序,比如第一个粉丝抢到了23元,第二个粉丝抢到了90元..依次类推...
要求:
每个红包只能发出去一次,哪个红包先输出是随机的, 6个红包必须正好是输出完。
代码
public class Test55 {
public static void main(String[] args) {
sendRedPackage();
}
public static void sendRedPackage(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要发的红包个数:");
int redPageNum = sc.nextInt();
int[] redPage =new int[redPageNum];
System.out.println(redPage.length);
for (int i = 0; i < redPage.length; i++) {
while (true){
System.out.println("请输入第"+(i + 1)+"个红包的金额:");
int redMoney = sc.nextInt();
if (redMoney >= 0 && redMoney <= 100){
redPage[i] = redMoney;
break;
}else {
System.out.println("红包范围不在 1 - 100之间");
}
}
}
printArr(redPage);
//发红包
Random r = new Random();
for (int i = 0; i < redPage.length; i++) { //0 1 2
System.out.println("第"+(i + 1)+"个粉丝抢到了");
while (true){
int index = r.nextInt(redPage.length); //0 3 2
int money = redPage[index]; // 23 32 4
if (money != 0){
System.out.println(money);
redPage[index] = 0; //[0,54,4,32,54] [0,54,4,0,54] [0,54,0,0,54]
break;
}
}
}
}
public static void printArr(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println("");
}
}
第六题:生成一组双色球红球号码
题目: 编写一个Java程序,能 随机出一组双色球红球号码.(可不用定义方法解决)
要求:
双色球红球号码总共有6个,从1--33中选择,要求6个号码不能重复。
需要输出最终生成的一组红球号码
代码
public class Test66 {
public static void main(String[] args) {
getRedNumber(6,33);
getRedNumber(16,66);
}
/**
* 生成一个,随机位数,并且1 - n范围的双色球
* @param num
* @param bound
*/
public static void getRedNumber(int num,int bound){
int[] arr = new int[num];
Random r = new Random();
for (int i = 0; i < arr.length; i++) {
while (true){
int index = r.nextInt(bound)+ 1; // 12
int arrData = checkArrData(arr, index);
// System.out.println(arrData);
if (arrData == -1){
arr[i] =index;
break;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println("");
}
public static int checkArrData(int[] arr,int data){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == data){
return i;
}
}
return -1;
}
}
面向对象
一,面向对象入门
面向对象是java的核心课程。因为写java程序是有套路的,而面向对象就是写java程序的套路;如果我们不知道面向对象编程,那么java编程算是白学了。
假设我们需要处理的是学生的姓名,语文成绩,数学成绩这三个要素,要求打印输出这个学生的总成绩和平均成绩。
遇到这样的需求,我们都会定义方法来做。
public class Student {
String name;
double chineseScore;
double mathScore;
public void printTotalScpre(String name,double chineseScore,double mathScore){
System.out.println(name+"同学的成绩总和是:"+(chineseScore+mathScore));
}
public void printAvgScore(String name,double chinese,double mathScore){
System.out.println(name+"同学的平均分是:"+(chinese+mathScore)/2);
}
}
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
s1.printTotalScpre("小明",100,50);
s1.printAvgScore("小明",100,50);
}
}
上面的案例是通过面向过程的编程方式。所谓的面向过程就是编写一个方法,有数据要进行处理就交给方法来处理。
public class Student {
String name;
Double score;
public void checkSuccess(Double score){
//如果不加this,就会出现变量名冲突的问题,导致这个判断的参数就是方法传过来的参数,就没有访问到这个对象的属性。
if (this.score >= score){
System.out.println(name+",恭喜你考上了清华");
}else {
System.out.println(name+",很遗憾落榜了");
}
}
}
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "李哈哈";
s1.score = 240.0;
s1.checkSuccess(250.0);
}
所谓的面向对象编程,就是把要处理的数据交给对象,让对象来处理。
二,深刻认识面向对象
2.1 面向对象有什么好处?
java的祖师爷认为,世界中 万物皆对象!任何一个对象都可以包含一些数据,数据属于那个对象,就由那个对象来处理。
2.2 程序中的对象到底是个啥?
对象实质上是一种特殊的数据结构。这种结构怎么理解呢?
我们可以把对象理解成一张表格,表格中记录的数据,就是对象拥有的数据。
一句话总结:对象可以理解成一张数据表,而数据表中可以有哪些数据,是有类来设计的。
三,对象在计算机中的执行原理
按照我们之前将的数组的执行原理,数组变量记录的其实是数组在堆内存中的地址。其实面向对象的代码执行原理和数组的执行原理是非常简单的。
Student s1 = new Student(); 这句话的理解如下:
- Student s1 表示的是在栈内存中,创建一个Student类型的变量,变量名为s1
- 而 new Student() 会在堆内存中创建一个对象,而对象中包含学生的属性名和属性值。同时系统会为这个Student对象分配一个地址值 0x4f3f5b24
- 接着把对象的地址赋值给栈内存中的变量s1,通过s1记录的地址就可以找到这个对象。
- 当我们执行s1.name="波妞"时,其实就是通过s1找到对象的地址,在通过对象找到对象的name属性,在给对象的name属性赋值为"波妞"
搞明白Student s1 = new Student();
的原理之后,Student s2 = new Student();
原理完全一样,只是在堆内存中重新创建了一个对象,又有一个新的地址。s2.name
是访问另对象的属性。
四,类和对象的一些注意事项
- 类名建议使用英文单词,首字母大写,满足驼峰模式,且要有意义。比如:Student Animal
- 类中定义的变量称为成员变量(对象的属性)类中定义的方法称为成员方法(对象的行为)
- 成员变量本身存在默认值
- 一个代码文件中,可以写多个class类,但只能一个用plblic修饰,且public修饰的类名必须成为代码文件名。
- 对象与对象之间的数据不会相互影响,但多变量指向同一个对象就会相互影响了。
- 如果某个对象没有一个变量引用它,该对象无法被操作,该对象会成为所谓的垃圾对象
一个代码文件中,可以写多个class类,但是只能有一个是public修饰,且public修饰的类必须和文件名相同。
假设文件名为Demo1.java
,这个文件中假设有两个类Demo1类和Student类
,代码如下
//public修饰的类Demo1,和文件名Demo1相同
public class Demo1{
}
class Student{
}
对象与对象之间的数据不会相互影响,但是多个变量指向同一个对象会相互影响。
如下图所示,s1和s2两个变量分别记录的是两个对象的地址值,各自修改各自属性值,是互不影响的。
五,this关键字
this是什么呢?
this就是一个变量,用在方法中,可以拿到当前类的对象
我们看下图所示代码,通过代码来体会这句话到底是什么意思。哪一个对象调用方法方法中的this就是哪一个对象
分析上面的代码s3.score = 325,调用方法printPass方法时,方法中的this.score 也是325;而方法中的蚕食score接收的是250.执行结果是:
最后我们重点记住这句话:哪一个对象调用方法中的this就是哪一个对象
六,构造器
6.1 什么是构造器:
构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相同。
如下图所示:下面有一个Student类,构造器名称也必须叫Student;也有空参数构造器,也可以有有参数构造器。
6.2 构造器的特点:
在创建对象时,会调用构造器。
也就是说 new Student() 就是在执行构造器,当构造器执行完了,也就意味着对象创建成功
关于构造器的特点我们记住一句话:new对象就是在执行构造器
6.3 构造器的应用场景:
其实构造器就是用来创建对象的。可以在创建对象时给对象的属性做一些初始化操作。如下图所示:
6.4 构造器的注意事项
1.在设计一个类时,如果不写构造器,Java会自动生成一个无参数构造器。
2.一定定义了有参数构造器,Java就不再提供空参数构造器,此时建议自己加一个无参数构造器。
关于构造器的最后总结:
1.什么是构造器?
构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相 同。
2.构造器什么时候执行?
new 对象就是在执行构造方法;3.构造方法的应用场景是什么?
在创建对象时,可以用构造方法给成员变量赋值4.构造方法有哪些注意事项?
1)在设计一个类时,如果不写构造器,Java会自动生成一个无参数构造器。
2)一定定义了有参数构造器,Java就不再提供空参数构造器,此时建议自己加一个无参数构造器。
七 封装性:
7.1 什么是封装?
所谓封装,就是用类设计对象处理某一个事物的数据时,应该把要处理的数据,以及处理数据的方法,都设计到一个对象中去。
比如在设计学生类的时候,把学生对象的姓名,语文成绩,数学成绩三个属性。以级求学生的总分,平均分方法,都封装到学生对象中。
封装设计规范的8字总结就是:合理隐藏,合理暴露
比如,设计一辆汽车时,汽车的发动机、变速箱等一些零件并不需要让每一个开车的知道,所以就把它们隐藏到了汽车的内部。
把发动机、变速箱等这些零件隐藏起来,这样做其实更加安全,因为并不是所有人都很懂发动机、变速箱,如果暴露在外面很可能会被不懂的人弄坏。
7.2 封装在代码中的体现
一般我们周期设计一个类时,会将成员变量隐藏,然后把操作成员变量的方法对外暴露。这里需要用到一个修饰符,叫private,被private修饰的变量或者方法,只能在本类中被访问。
priavte double score;就是相当于把score变量封装在了,Student对象内部,且不能对外暴露,如果我们想要在其他类中访问score这个变量,就不能直接访问。
如果你想给Student对象的score属性赋值,得调用对外暴露的方法setScore(int score)
,在这个方法中可以对调用者传递过来的数据进行一些控制,更加安全。
当我们想获取score变量时,就得调用对外暴露的另一个方法 getScore()
public class Teacher {
String name;
double salary;
char sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public void printThis(){
System.out.println(this);
}
}
八,实体类javaBean
接下来,我们学习一个面向对象编程中,经常写的一种类——叫实体JavaBean类。我们先来看什么是实体类?
8.1 什么是实体类?
实体类就是一种特殊的类,它需要满足下面的需求:
我们按照要求写一个Student实体类:
我们会发现实体类中除了有给对象存、取值的方法就没有提供其他方法了。所以实体类仅仅只是用来封装数据用的。
8.2 实体类的应用场景:
在实际开发中,实体类仅仅只用来封装数据,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离。如下图所示
如下图所示,在StudentOperator类中,定义一个Student类型的成员变量student,然后使用构造器给student成员变量赋值。
然后在Student的printPass()方法中,使用student调用Student对象的方法,对Student对象的数据进行处理。
总结:
1.JavaBean实体类是什么?有啥特点
JavaBean实体类,是一种特殊的;它需要私有化成员变量,有空参数构造方法、同时提供 getXxx和setXxx方法;
JavaBean实体类仅仅只用来封装数据,只提供对数据进行存和取的方法
2.JavaBean的应用场景?
JavaBean实体类,只负责封装数据,而把数据处理的操作放在其他类中,以实现数据和数 据处理相分离。
九 面向对象的综合案例:
根据动物和实际小动物来编写程序:
第一步:定义Animal类:
public class Animal {
private String name;
private Double weight;
private int age;
private char sex;
private Double score;
public Animal() {
}
public Animal(String name, Double weight, int age, char sex,double score) {
this.name = name;
this.weight = weight;
this.age = age;
this.sex = sex;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
}
第二步:定义AnimalOperator业务逻辑类:
public class AnimalOperator {
private Animal a;
public AnimalOperator(Animal a){
this.a = a;
}
/**
* 检查是否及格
*/
public void printScore(){
if (a.getScore() >= 60){
System.out.println(a.getName()+"及格了");
}else {
System.out.println(a.getName()+"挂科了");
}
}
public void printScoreGrade(){
double score = a.getScore();
if (score >=0 && score < 60){
System.out.println(a.getName()+"你的成绩等级是:D");
} else if (score >= 60 && score < 80) {
System.out.println(a.getName()+"你的成绩等级是:C");
} else if (score >= 80 && score < 90) {
System.out.println(a.getName()+"你的成绩等级是:B");
} else if (score >= 90 && score <= 100) {
System.out.println(a.getName()+"你的成绩等级是:A");
}
}
}
第三步:定义测试类:
public class Test {
public static void main(String[] args) {
Animal a1 = new Animal("猴子",129.1,21,'男',100);
Animal a2 = new Animal("小乔",94.2,18,'女',45.5);
AnimalOperator ao1 = new AnimalOperator(a1);
ao1.printScore();
ao1.printScoreGrade();
AnimalOperator ao2 = new AnimalOperator(a2);
ao2.printScore();
ao2.printScoreGrade();
}
}
根据电影类编写相应的信息:
第一步:先定义电影类:
public class File {
private int id;
private String name;
private double price;
private String director;
private String desc;
public File() {
}
public File(int id, String name, double price, String director, String desc) {
this.id = id;
this.name = name;
this.price = price;
this.director = director;
this.desc = desc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
第二步:编写电影业务逻辑类:
public class FileOperator {
private File[] f;
public FileOperator(File[] f){
this.f = f;
}
/**
* 遍历全部的电影数据
*/
public void getAllFiles(){
System.out.println("全部的电影:");
for (int i = 0; i < f.length; i++) {
File file = f[i];
System.out.println("编号:"+file.getId()+" 名称:"+file.getName()+" 价格:"+file.getPrice()+" 导演:"+file.getDirector()+" 描述:"+file.getDesc());
}
}
/**
* 根据id查询电影数据
*/
public void getFileById(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要查询的电影:");
int id = sc.nextInt();
boolean flag = false;
for (int i = 0; i < f.length; i++) {
File file = f[i];
if (file.getId() == id){
System.out.println("编号:"+file.getId()+" 名称:"+file.getName()+" 价格:"+file.getPrice()+" 导演:"+file.getDirector()+" 描述:"+file.getDesc());
flag = true;
}
}
if (!flag){
System.out.println("没有查询到电影数据");
}
}
}
第三步:定义测似类:
public class Test {
public static void main(String[] args) {
File[] files = new File[9];
files[0] = new File(1,"坚如磐石",33.4,"梨花哈","非常的精彩");
files[1] = new File(2,"孤注一掷",19.9,"张艺哈","真的超级刺激");
files[2] = new File(3,"封神榜",23.7,"路小子","可以很奈斯");
files[3] = new File(4,"长安三万里",55.4,"立白","真好看");
files[4] = new File(5,"满江红",11.3,"吼吼吼","期待下一部");
files[5] = new File(6,"保你平安",9.0,"宫本","好看,好看");
files[6] = new File(7,"兄触目",55.6,"为止","好看,精彩");
files[7] = new File(8,"流浪地球",23.6,"你猜","好看,还是很不错的");
files[8] = new File(9,"熊熊乐园",28.1,"酷酷酷","好看,中中");
FileOperator fileOperator = new FileOperator(files);
fileOperator.getAllFiles();
fileOperator.getFileById();
}
}
十,成员变量和局部变量的区别:
如下图所示,成员变量在类中国方法外,而局部变量在方法外:
到这里,我们关于面向对象的核心点就是封装,讲数据和数据的处理方式,都封装到对象中;至于对象要封装那些数据?对数据进行怎么的处理?需要通过类来设计。
面向对象高级:
在我们这节面向对象里面需要学习的内容:
static
static修饰成员变量:
static 叫静态:可以修饰成员变量,成员方法。
成员变量:按照有无static修饰分为两种:
- 静态变量(类变量)
- 实例变量(对象的变量)
成员变量的执行原理:
xtatic修饰成员变量的应用场景:
在开发中,如果某个数据只需要一份,且希望能够被共享(访问,修改)则该数据可以定义成类变量。
导学案例:
static修饰成员方法:
静态方法(类方法):有static修饰的成员方法,属于类
实例方法:无static修饰的成员方法,属于对象。
成员方法的执行原理:
补充知识,搞懂main方法:
static修饰成员方法的应用场景:
静态方法最常见的应用场景是做工具类
工具类是什么?
工具类中的方法都是一些静态方法,每个方法都是用来完成一个功能,工具类是给开发人员共同使用的。
优点:提高了代码的复用性,提高开发效率。
为什么工具类中的方法要用静态方法,而不是实例方法?
- 静态方法调用更方便,同时可以避免浪费内存。
- 如果是使用实例方法,则需要创建对象来调用,此时对象只是为了调用方法,二对象本身要占内存,这样会浪费内存。
由于工具类没有创建对象的需求,建议讲工具类的构造器进行私有化
Math
代表数字,是一个工具类,里面提供的都是对数据进行操作的一些静态方法
math类提供的常见方法:
代码:
public static void main(String[] args) {
System.out.println(Math.abs(-123)); //123
System.out.println(Math.abs(66)); //66
System.out.println("--------");
System.out.println(Math.ceil(4.499)); //5.0
System.out.println(Math.ceil(6.00001)); // 7.0
System.out.println("---------");
System.out.println(Math.floor(1.999)); //1.0
System.out.println(Math.round(3.49)); //3
System.out.println(Math.round(7.5001)); //8
System.out.println("---------");
System.out.println(Math.random()); //0.48094281660352267
}
static的注意事项:
- 静态方法中可以直接访问类的静态成员,不可以直接访问实例成员。
- 实例方法中既可以直接访问静态成员,也可以直接访问实例成员。
- 实例方法中可以使用this关键字,静态方法中不可以使用this关键字
代码块:
代码块是类的5大成分之一(成员变量,构造器,方法,代码块,内部类)
代码块分为两种:
- 静态代码块:
格式:static{}
特点:类加载是自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
作用:完成类的初始化。例如:对类的变量初识化赋值。
- 实例化代码块
格式:{}
特点:每次创建对象时,执行实例代码块,并在构造器前执行。
作用:和构造器一样,都是用来完成对初始化的。例如:对实例变量进行初始化赋值
单例设计模式:
什么设计模式(Design pattern)
- 一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
- 设计模式有20多种,对应20多种软件开发中会遇到的问题。
单例设计模式:
确保一个类只能创建一个对象
写法:
- 把类的构造器私有。
- 定义一个静态变量记住类的一个对象。
- 定义一个静态方法,返回对象。
代码: 饿汉式--拿对象时,对象已经创建好了。
/**
* 单例模式
*/
public class DanDemo {
// 1 提供类变量接收
private static DanDemo danDemo = new DanDemo();
// 2 私有化构造器
private DanDemo(){
}
// 3 提供静态方法
public static DanDemo getDanDemo(){
return danDemo;
}
}
懒汉式--拿对象时,才开始创建对象
public class EhDemo {
// 2,提供一个实例
private static EhDemo ehDemo;
// 1 把类的构造方法私有化
private EhDemo(){}
// 3 提供一个对外的静态方法
public static EhDemo getEhDemo(){
if (ehDemo == null){
ehDemo = new EhDemo();
}
return ehDemo;
}
}
java常用API
一,API概述
常用API(全称是Application Program Interface 应用程序接口),说人话就是:别人写好的一些程序,给咱们程序员直接拿去调用。
Java官方其实已经给我们写好了很多很多类,每一个类中又提供了一系列方法来解决与这个类相关的问题。
-
比如String类,表示字符串,提供的方法全都是对字符串操作的。
-
比如ArrayList类,表示一个容器,提供的方法都是对容器中的数据进行操作的。
1,我们为什么要学习别人写好的程序呢?
Java已经发展了20多年,在这20多年里,已经积累类了很多问题的解决方案,基本上现在我们遇到的问题,在这20多年里,早就有人解决过。
所以我们把面向对象的高级知识学习完之后,Java语言的语法知识就已经学习完了。剩下的所有内容都是是学习一个一个的API,通过调用API提供的方法来解决实际问题。
2,我们要学习那些API
Java的API文档中,有那么多的类,是所有的类都要学习吗?并不是 ,虽然Java提供了很多个类,但是并不是所有类都得到了市场认可,我们只学习一些在工作中常用的就行。
除了Java官方提供的API,还一些第三方的公司或者组织也会提供一些API,甚至比Java官方提供的API更好用,在需要的时候我们也会告诉大家怎么用。
3,今天我们主要学习两个类,一个String类,还有一个是ArrayList
String 字符串:
String 代表字符串对象,可以用来封装字符数据,并提供了很多操作字符串的方法。
字符串的应用场景是非常多的,可以说是无处不在。
比如,在用户登录时,需要对用户名和密码进行校验,这里的用户名和密码都是String
再比如,在和网友聊天时,其实输入的文字就是一个一个字符串
再比如,在百度上搜索时,搜素的关键词,也是字符串
String创建对象封装字符串的方式:
方式一:java程序中的所有字符串(例如文字‘abc’)都为此类的对象。
String name = "黑子";
String schoolName = "某某科技大学";
方式二:调用String类的构造器初始化字符串对象。
代码:
public static void main(String[] args) {
//直接使用""
String str= "123abc";
System.out.println(str);
//根据传入的字符内容创建对象
String s = new String("666哈哈");
System.out.println(s);
String s1 = new String();
String s2 = new String();
System.out.println(s1);
System.out.println(s2);
//根据字符数组创建对象
byte[] b = {97,98,99,'a','b','c'};
String ss = new String(b);
System.out.println(ss);
}
String的常用方法:
代码:
public class StringDemo2 {
public static void main(String[] args) {
// 目标:快速熟悉String提供的处理字符串的常用方法。
String s = "123大大怪开心超人";
// 1、获取字符串的长度(字符个数)
System.out.println(s.length());
// 2、提取字符串中某个索引位置处的字符
char c = s.charAt(5);
System.out.println(c);
for (int i = 0; i < s.length(); i++) {
char charAt = s.charAt(i);
System.out.print(charAt);
}
System.out.println(" ");
// 3、把字符串转换成字符数组,再进行遍历
System.out.println("------------------");
String ss = "abc学java现在就开始吧";
char[] charArray = ss.toCharArray();
for (int i = 0; i < charArray.length; i++) {
System.out.print(charArray[i]);
}
System.out.println("");
// 4、equals: 判断字符串内容,内容一样就返回true (重点)
System.out.println("-----------------------");
String p1 = new String("abc");
String p2 = new String("abc");
String p3 = new String("aBC");
System.out.println(p1 == p2); //false
System.out.println(p1.equals(p2)); //true
// 5、忽略大小写比较字符串内容
System.out.println(p1.equalsIgnoreCase(p3)); //true
// 6、截取字符串内容 (包前不包后的)
String str = new String("一起来学习java课程吧非常好玩");
System.out.println(str.substring(5, 11));
// 7、从当前索引位置一直截取到字符串的末尾
System.out.println(str.substring(3));
System.out.println("-------------------");
// 8、把字符串中的某个内容替换成新内容,并返回新的字符串对象给我们
// 敏感词替换
String pingLun = "什么垃圾队友真菜,都不知道支援,垃圾队友,还不过来支援!!";
System.out.println(pingLun.replace("垃圾", "**"));
// 9、判断字符串中是否包含某个关键字
String str2 = "开心的亚瑟";
System.out.println(str2.contains("亚瑟")); //true
System.out.println(str2.contains("狗娃")); //false
// 10、判断字符串是否以某个字符串开头。
String str3 = "子哈天天都在干嘛呢不是在玩吧";
// startsWith 判断是否以什么内容开头
System.out.println(str3.startsWith("子哈")); //true
System.out.println(str3.startsWith("子哈2")); //false
// endsWith 判断是否以什么内容结尾
System.out.println(str3.endsWith("玩吧")); //true
System.out.println(str3.endsWith("玩吧2")); //false
// 11、把字符串按照某个指定内容分割成多个字符串,
// 放到一个字符串数组中返回给我们。
// 孙尚香,宫本武藏,李白,鲁班
String sstr = new String("孙尚香,宫本武藏,李白,鲁班");
String[] strings = sstr.split(",");
System.out.println("你勾选的英雄是:");
for (int i = 0; i < strings.length; i++) {
System.out.print(strings[i] +" ");
}
}
}
String使用时的注意事项:
1,String的对象是不可变的字符串:
注意:只要是以 "" 方式写出的字符串对象,会在堆内存中的所有字符串常量池中存储
每次试图改变字符串对象实际上是新产生了新的字符串对象了。每次变量都是指向了新的字符串对象,之前字符串对象的内容确实没有改变,因此说String的对象是不可变的。
String的第二点注意事项:
通过""定义字符串内存原理
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
}
java为什么这么设计?节约内存。
示例:通过new构造器得到字符串对象
代码
public static void main(String[] args) {
char[] chs = {'a','b','c'};
String s1 = new String(chs);
String s2 = new String(chs);
System.out.println(s1 == s2); //false
}
案例:阅读程序并回答问题:
解析:
案例:阅读下面的程序,请写出程序打印的结果是什么
String s1 = "abc";
String s2 = "ab";
String s3 = s2+"c";
System.out.println(s1 == s3); //false
String s1 = "abc";
String s2 = "a"+"b"+"c";
System.out.println(s1 == s2); //true
案例-完成用户登录:
代码:
public class StringDemo3 {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的登录名:");
String loginName = sc.next();
System.out.println("请输入你的密码:");
String loginPwd = sc.next();
System.out.println(loginName+loginPwd);
String okName = "heima";
String okPwd = "123456";
if (loginName.equals(okName)){
if (loginPwd.equals(okPwd)){
System.out.println("恭喜你,系统登录成功");
break;
}else {
System.out.println("密码错误");
}
}else {
System.out.println("账号匹配失败");
}
}
}
}
案例2 使用String开发验证码
代码:
public class StringDemo4 {
public static void main(String[] args) {
System.out.println(createCode(6));
System.out.println(createCode(10));
}
/**
* 生成随机位数的验证码
* @param n
* @return
*/
public static String createCode(int n){
String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String code = "";
Random r = new Random();
for (int i = 0; i < n; i++) {
int index = r.nextInt(data.length());
code += data.charAt(index);
}
return code;
}
}