在阅读中如果有错误的地方还请斧正
一个Java文件(文本文件)需要运行,需要操作系统支持(Java运行环境 JRE: Java Runtime Enviroment)
Jre--->包含了JVM(Java虚拟机--->假象计算机 (有自己的网络,有自己的内存))
www.oracle.com :oracle官网里面提供 jdk(Java development Kit :Java开发工具包)---包含了jre
自己的操作系统上只需要安装jdk就可以!(自己使用的是JDK-8)
Java代码需要备java虚拟机进行编译和执行(javac和Java指令)
通过在bin目中书写简易的Java代码,来了解java程序。
1)在jdk的bin目录里面新建一个HelloWorld.txt
2)编写Java代码的固定格式(//为代码注解,不会被运行;在书写代码时使用英文字符)
class HelloWorld{ //Java中最基本的单元 "类" 定义格式 class 类名{},建议类名和文件名称的前缀一致
//固定格式:Java程序的入口函数:它是能这个假象计算机(java虚拟机)进行调用的(执行)
public static void main(String[] args){
//Java中固定的输出语句 ""里面的内容不断改动的
System.out.println("helloworld") ; //""称为 "字符串"
}
}
3)将.txt文件扩展名改为 ".java",在设置中:查看--->显示--->拓展名。
4)①打开dos窗口(dos控制台) windows键+r键--->输入cmd--->然后使用dos的基本指令找到对应文件的路径--->使用javac和Java指令对代码进行编译、解释、运行
直接在图中位置输入cmd--->输入javac HelloWorld.java--->回车--->输入java HelloWorld--->回车即可,就会看到helloworld
class:Java中最基本的单元 "类" 定义格式 class 类名{},建议类名和文件名称的前缀一致
HelloWorld:类名
public、static、void:在Java中是关键字,具有特殊含义,由小写的字母组成。
main方法:称为主方法。写法是固定格式不可以更改。main方法是程序的入口点或起始点,无论 我们编写多 少程序,JVM在运行的时候,都会从main方法这里开始执行。
String:类代表字符串。Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。
System.out.println() :Java中固定的输出语句 ""里面的内容不断改动的,""称为 "字符串",在括号里也可以编写其他内容输出。
如果不配置系统环境变量,永远只能在jdk安装目录中bin目录里面去使用javac和java指令,对java编译和运行!
配置是为了让我们在任何目录中都能够使用javac和java指令!
1)复制jdk安装目录的bin目录的路径举例:D:\develop_software\Java\jdK_8\bin
2)此电脑--->右键属性---->高级系统设置---->环境变量----->系统环境---->找到path双击path,然后新建,将上面路径复制到path中(放在最前面)
3)退出dos窗口,重写打开新的dos窗口,在任何目录中进行编译和运行!
方式1配置的弊端
1)不安全,当jdk版本切换,需要手动更改系统变量中path,可能会导致别的环境变量被误删!
2)这种方式后期 学习"web应用服务器" tomcat(用java编写的),启动会闪屏(启动失败),tomcat服务器启动的时候会寻找系统变量是否有"JAVA_HOME"的变量,如果存在,tomcat启动不会闪屏!
1)复制jdk安装路径(不需要bin目录的路径)
举例:D:\develop_software\Java\jdK_8
2)此电脑--->右键属性---->高级系统设置---->环境变量----->系统环境---->
新建一个变量名
变量名 JAVA_HOME
变量值 上的jdk的安装路径
3)在path中的路径上使用 %JAVA_HOME%\bin
优点:
1)安全,即使jdk升级,不需要改动系统变量中path路径,只需要更改JAVA_HOME对应的路径
2)后期使用tomcat web服务器的时候,不会出现闪屏!
1)先要去在指定目录中(文件夹)找是否存在这个 xxx.java文件,如果存在这个文件就直接编译然后运行字节码的前缀
2)如果当前指定的目录中(文件夹)如果不存在xxx.java文件,那么就需要在系统变量path中 %JAVAH_H0ME%\bin
这个路径去寻找是否存在,如果存在,就编译,如果也不存在,那么说明系统中不存在这个文件 "找不到文件!"
在普通记事本书写java代码,默认保存的字符集utf-8 (一个中文对应是三个字节)
而dos控制台黑窗口里面的默认的字符集格式:"gbk",一个中文对应两个字节
在dos窗口中执行文件如果是"utf-8"出现乱码
解决方案:
本地写的文本文件--选择另存为"ANSI" (gbk格式),就能在dos中进行编译和运行
java程序开发三步骤:编写、编译、运行。
javac.exe:编译器
java.exe:解释器
当编写好源程序后,使用javac指令会对文件进行编译后会在对应路径下生成对应类的字节码文件(类名+class),然后使用java指令会对字节码文件进行解释和运行。
编译:是指将我们编写的Java源文件翻译成JVM认识的class文件,在这个过程中, javac 编译器会 检查我们 所写的程序是否有错误,有错误就会提示出来,如果没有错误就会编译成功。 运行:是指将 class文件 交给JVM去运行,此时JVM就会去执行我们编写的程序了。
1)盘符切换盘符号后面:(盘符号不区分大小写)
C:\Users\Administrator>D:
D:\>
2)dir罗列当前盘符或者指定文件夹中所有的文件以及文件的名称(详细信息)
3)当dos窗口内容比较多,清屏命令 cls (clear screen:清除屏幕)
D:\>cls
4)cd 目录名称(文件夹名称) :进入指定的目录中cd(change Directory)
D:\>cd ee_2302
D:\EE_2302>
5)cd.. 回退上一级目录
D:\EE_2302\day2>cd..
D:\EE_2302>
6)cd 多级目录名称:进入指定路径的文件夹中
D:\>cd D:\EE_2302\day2\code
D:\EE_2302\day2\code>
7)cd \ 从多级目录中回退到根目录
D:\EE_2302\day2\code>cd \
D:\>
8)md 目录名称(文件夹名称):创建文件夹 md(make directory)
D:\EE_2302\day2\code>md aaa
D:\EE_2302\day2\code>
9)创建文件 copy con 文件名称 --->按回车--->进入编辑模式(编辑文件内容)---->按 ctrl+z:保存--->按回车--->创建完成
D:\EE_2302\day2\code\aaa>copy con aaa.txt
这是一个txt文件^Z
已复制 1 个文件。
D:\EE_2302\day2\code\aaa>
10)删除指定的文件 del 文件名称
D:\EE_2302\day2\code\aaa>del a.java
D:\EE_2302\day2\code\aaa>
11)批量删除所有的指定后缀的文件 del *.xx
D:\EE_2302\day2\code\aaa>del *.txt批量删除所有带.txt后缀的文件
D:\EE_2302\day2\code\aaa>
12)删除目录(文件夹) rd 目录名称 (前提条件:这个目录必须为空目录,否则系统提示"目录不是空的")
D:\EE_2302\day2\code>rd aaa
目录不是空的。
D:\EE_2302\day2\code>
传统删除带内容的目录:需要先进入到指定目录中,删除里面的内容;然后回退上一级目录,删除当前文件夹!
13)rd扩展指令: rd /s 目录名称(询问是否删除带内容目录)
D:\EE_2302\day2\code>rd /s aaa
aaa, 是否确认(Y/N)? y
D:\EE_2302\day2\code>
14)rd扩展指令 rd /s /q 目录名称(暴力删除,不询问直接干掉)
D:\EE_2302\day2\code>rd /s /q 高圆圆
D:\EE_2302\day2\code>
俗称"电脑",没有任何软件的计算机 "裸机"!
计算机的分类:台式计算机,笔记本,大型计算机(公司的机房)
1)科学计算
2)多媒体应用
3)计算机辅助设计 ----CAD工程制图
4)人工智能
5)计算机网络
1)硬件:机械,光电元件的物理装置的总称: cpu,电源,主机箱,显卡,键盘,鼠标,主板,显示器....
2)软件:
①系统软件:
pc端: Windows,Linux,Mac
移动端:android,ios
②应用软件:
计算机安装的客户端软件:QQ客户端、微信、yy语音
C/S结构
Client/Server:客户端和服务器端的交互
典型特点:客户端必须升级,才能使用 服务器高版本的功能: 比如QQ
B/S结构
Browser/Server:浏览器端和服务器端的交互
典型的特点:只要保证计算机上有浏览器,那么就可以访问服务器高版本功能!(浏览器本地可以不升级)
程序员专用浏览器
"firefox 火狐" /谷歌浏览器
就是借助开发工具与计算机语言完成软件的制作过程(制作过程中,需要有计算机语言相关的数据和指令!)
开发工具:
前期---使用notepadd++ 高级记事本(写任何计算机语言代码的会有颜色标记),写代码
使用dos控制台进行编译和运行(javac/java指令)
熟练后:使用 idea2021 (自动编译/很智能化)
前端开发工具:HBuilderX或者vscode/webStorm(idea同一个公司的)
人和计算机之间沟通一种方式:
1)图形界面化:无论任何操作系统,都会有图形界面化(简单,直观,易于上手)
2)命令行方式:需要控制台 (Linux系统,Linux控制台终端输入一些命令)
windows系统:打开dos控制台,里面输入一些指令
windows系统打开dos控制台的方式:
1)开始菜单输入cmd---->命令行提示符---->以管理员身份打开
2)推荐方式: windows+r键--->输入"cmd"--->打开控制台
詹姆斯~高斯林 :Java之父 1995年正式推出"Java" "爪哇"
Jdk版本:目前使用的8版本/9版本 自己新特性
Java应用领域:比较广泛 360行几乎全部涵盖进去
1)电商平台
2)医院挂号系统
3)收银系统
4)健康码
5)比亚迪----MES系统 (传统行业)
6)物流系统
7)元宇宙
JAVASE:桌面应用程序
JAVAME:针对嵌入式设备提供一套解决方案
(移动端用到的 早期塞班系统,安卓系统) "看平台"
JAVAEE:针对企业级开发提供一套解决方案
很多特点 :安全性,健壮性,分布式....(学习到后期体会)
比较容易理解:
开源----->开发源代码---涉及的Java设计模式/数据结构/算法...
跨平台---->跨操作系统(不同的操作系统上都可以编译和执行 java文件)
临时环境变量
此电脑--->右键属性---->高级系统设置---->环境变量----->系统变量
新建一个变量名:classpath
变量值:要指定的那个class文件(字节码)的路径
配置完毕之后,在java 字节码文件前缀的时候---运行这个类的时候,始终是在classpath临时环境变量去执行对应.class文件,如果这个路径中没有class字节码文件,提示"找不到主类"!
什么是关键字?关键字:被赋予特定含义的单词!
在高级记事本notepad++或者editPlus,以及开发工具idea针对关键字都有
一种特殊颜色标记!
class:Java语言中定义类的格式!
public:权限修饰符号 (公开的/公共的,任何人都可以访问的,访问权限足够大)
static:静态修饰符号
void:和Java语言中定义方法(函数)一种格式
注意事项:
1)组成关键字的字母全部都是小写,而且特殊含义的!
2)goto 和const不作为关键字,保留字使用!
什么是标识符?在Java语言中,给包,类名,接口名,方法名,变量名,常量等等起名字一种"字符序列";
标识符的组成可以由26个英文字母(区分大小写)、数字、下划线(_)、$(美元符号)
①不能以数字开头 ②不能是Java中的关键字 ③区分大小写 ④不能是除下划线(_)和$之外的符号
起名字---做到四个字 "见名知意!"
1)给类名(或者接口名)起名字: 遵循格式 "大驼峰命名法" ("阿里规范")
类名是单个单词: 首字母大写,其余小写!
举例:
定义一个学生类:
class Student{}
class S{} 不规范
类名是多个单词:每个单词首字母大写,其余小写
举例:
定义有一个"玩游戏"的类
class PlayGameDemo{}
2)给变量(和方法就是函数)起名字:遵循"小驼峰命名法";
变量名是一个单词:字母全部小写
举例:
定义一个价格(默认int 整数)
int price = 100 ;
变量名是多个单词:第一个单词字母全部小写,
从第二个单词开始每一个单词首字母大写.其余小写
举例:
定义一个苹果价格
int applePrice = 100 ;
3)给常量(程序执行过程中,其值是固定的),起名字的时候:
常量是一个单词(开发中很少见):字母全部大写
举例:字符串常量 :双引号括起来的内容 "HELLO"
常量是多个单词(开发中经常见到):
每个单词字母都大写,单词和单词之间下划线隔开
JRE:Java Runtime Environment Java运行环境,包含jvm以及java文件运行所需要的核心类库 (lib--rt.jar)
JDK:Java Development Kit :Java软件开发工具包,包含jre以及工具文件(toos.jar)
JVM:Java Virtual Machine :Java虚拟机, 抽象化的计算机(在实际计算机上模拟各种功能)
三者的关系:JDK>JRE>JVM
JVM有自己的内存模型结构:
栈(本地方法栈,操作数栈...) ,堆,方法区,本地方法区,pc寄存器(程序计数器) 等等
Java文件需要运行在操作系统上,而操作系统需要有Java运行环境里面需要jvm来编译并且解析Java文件中的内容!
javac指令:负责编译编写好的源文件并生成字节码文件(.class)
java指令:负责解析java文件编译后的.class文件
作用: 1)提高代码阅读性 2)可以排错(利用注释可以逐句排查)
Java 支持三种注释方式。前两种分别是 //和/* */,第三种被称作文档注释,它以/**开始,以*/结束。
文档注释允许你在程序中嵌入关于程序的信息。你可以使用 javadoc 工具软件来生成信息,并输出到
HTML文件中。说明注释,使你更加方便的记录你的程序信息。
在开始的/**之后,第一行或几行是关于类、变量和方法的主要描述。
之后,你可以包含一个或多个各种各样的@标签。每一个@标签必须在一个新行的开始或者在一行的开始
紧跟星号(*)。多个相同类型的标签应该放成一组。例如,如果你有三个@see标签,可以将它们一个接一
个的放在一起。下面是一个类的说明注释的实例:
常量:在Java程序中固定不变的量称为常量。
①字面值常量(6种)
②自定义常量
变量:在Java程序中可以变化的量称为变量。在数学中变量X可以赋值5(X=5)也可以赋值为6(X=6),在Java中也可以使用字母存储数字,这样可以变化储存数值的量称为变量。
Java的数据类型分为两大类:
基本数据类型:整数、浮点数、字符、布尔
引用数据类型:类、数组、接口
基本数据类型(四类八种):
数据类型 |
关键字 |
内存占用 |
取值范围 |
|
整数 |
字节型 |
byte |
一字节 |
-128~127 |
短整型 |
short |
两字节 |
-32768~32767 |
|
整型 |
int(默认) |
四字节 |
-2的31次方~2的31次方-1 |
|
长整型 |
long(l) |
八字节 |
-2的31次方~2的31次方-1 |
|
浮点数 |
单精度浮点数 |
float |
四字节 |
1.4013E-45~3.4028E+38 |
双精度浮点数 |
double(默认) |
八字节 |
4.9E-324~1.7977E+308 |
|
字符 |
字符型 |
char |
两字节 |
0~65535 |
布尔 |
布尔类型 |
boolean |
一字节 |
true,false |
注:在Java中为了区分数据类型长整型(long)后要加l/L(例如:253l/253L);浮点类型的单精度浮点(float)后要加f/F(例如:253.1f/253.1F)
整数类型的默认类型是int;浮点类型默认是double。
基本类型使用居多:整数以及浮点/布尔boolean
整数类型:使用居多int类型,long(定义时间毫秒值)
浮点类型: double使用居多(市场价等等都会double)
布尔类型: 在一个具体业务场景的时候,大量会使用逻辑语句,需要用boolean
变量定义的格式包括三个要素:数据类型、变量名、数据值
格式:数据类型 变量名 = 数据值 ;
注:在同一个大括号内,变量的名字不可用相同
变量赋值:定义的变量不赋值不能使用。
Java程序中要求参与的计算的数据,必须要保证数据类型的一致性,如果数据类型不一 致将发生类型的转换错误。
例如上面两个变量相加byte类型的j会先转换为int类型,然后再和int类型的i相加,运算结果是int类型
转换规律:byte、short、char--->int--->long--->float--->double
byte、short、char相互之间不发生转换,一旦参与运算将自动转换为int类型;boolean类型不参与任何转换。
在Java中会自动将取值范围小的类型自动提升为 取值类型大的范围。可以理解为一个小的容器可以放到一个大的容器中
自动转换是小的数据类型可以转换为大的数据类型;强制转换就是把大的数据类型转化为小的数据类型;
这个格式不仅仅适用于基本数据类型,也适用于引用数据类型。
转换格式:数据类型 变量名 =(数据类型)被转数据值;(例:int i =(int)1.5 )
题目:
byte b = 300 ;
会出现什么情况?如何解决?计算结果分析
*/
class DataTypeDemo2{
public static void main(String[] args){
//byte b = 300 ; //定义变量
//byte类型的取值范围-128-127;已经超出了范围,默认int类型
//解决方案:强转
//目标类型 变量名 = (目标类型)(初始化值或者表达式) ;
byte b = (byte)300;
//System.out.println(b) ;
//double x = 1.1/0.0 ;
System.out.println(x) ;
}
}
/*
300---默认int类型 4个字节
最高符号位 数值位
00000000 00000000 00000001 00101100 原码,反码,补码
计算机底层是补码进行数据的计算
byte b = (byte)300;
(00000000 00000000 00000001) 00101100
截取之后:就是00101100---补码--反码--原码 44
*/
进制:也属于常量的范畴
什么是进制:是数据进位的一种方式;
进制的种类:
1)二进制:逢二进一,由0,1组成---以0B/0b开头(0B/0b用来表示二进制)
2)八进制:逢8进1,由0,1,2,3,4,5,6,7组成---以0开头
3)十进制:整数就是
4)十六进制:逢16进1,由0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f---以0x/0X开头
8421码
运算符:就是程序中的操作符号
种类:算术运算符、赋值运算符、关系(比较)运算符、逻辑运算符、三目运算符 扩展:位运算符
算术运算符:
基本算术运算符: +,-,*,/,%
注意:
/(除):默认取整 (java是强类型语言,弱类型javascript前端语言不会默认取整)
%:模:求余数
扩展的算术运算符:++和-- (使用比较多的):
两种用法:
1)单独使用----流程语句中--循环语句使用居多
++或者--在数据的前面:
++或者--在数据的后面:
结论:无论在数据的前面还是数据的后面:都是自增1或者自减1
2)参与运算使用
++或者--在数据的前面:
先进行自增或者自减,然后参与运算
++或者--在数据的后面:
先运算,然后当前变量本身自增或者自减
1) int a = 10;
int b = 10;
int c = 10;
a = b++; //a=10,b=11 c=10;
c = --a; //a=9, b=11,c=9;
b = ++a; //a=10,b=10, c=9;
a = c--; //a=9, b=10,c=8 ;
2)比较复杂的题目
int x = 4;//x=4 -->5---6
int y = (x++)+(++x)+(x*10);---可以将括号看成可以赋值的变量---int y = a+b+c
x的值刚开始为4--->(x++):++在变量的后面先把变量x的值赋值给a,然后再自增变为5--->(++x):++在变量后面,变量先自增变成6然后赋值给b--->(x*10):6*10=60
//y= 4 + 6 + 60
=70
基本的赋值运算符:=--->将=号右边的值赋值给左边指定类型的变量
举例:
int x = 10 ;
将10赋值给int类型的变量x
注意:=不能写成==,==不能写成= (==是比较运算符)
+=,-=,*=,/=,%= :将等号右边的数据和左边的变量值操作,在赋值给左边的变量
举例:
int x = 10 ;
x += 20 ;----->等价于 x = x + 20 ;(前提条件:类型相同)
将=等号左边的变量和右边的值相加在赋值给左边的变量x(拓展的赋值运算符具有强转的性质,当运算的数据类型不相同时将右边的数据类型强转为左边的数据类型)
short s = 1 ;
s+=1 ; ----->等价于 s = (short)(s+1) ;
例题:
*/
class OperatorDemo{
public static void main(String[] args){
//定义一个变量
int x = 10 ; //将10给int类型变量x
//int y == 20 ; //==是比较运算符,y是没有值的;
System.out.println("x:"+x) ;
System.out.println("----------------------------------") ;
//定义一个变量m
int m = 100 ;
m += 200 ; //等价于 m = m + 200 ;
System.out.println("m:"+m) ;
}
}
关系(比较)运算符(最简单一种运算符)
<,>,<=,>=,==,!=
这些符号连接的表达式无论简单还是复杂的结果都是boolean值!
==:在基本数据类型中,比较两个数据值是否相等
注意事项: ==不能写成 "="
数学表达式:3<=x<=5, 计算机语言中:必须使用逻辑符号连接!
例题:
int x = 100 ;
int y = 200 ;
//定义变量接收x和y比较的结果
//boolean flag = x= y ; 将y的值给x,将x值留下来赋值给flag,boolean不参与运算!
boolean flag = (x==y) ;
System.out.println(flag) ;--->结果为:false
逻辑运算符号(开发中经常用到)
基本的逻辑运算符号:
逻辑与&:具有并列条件,所有的条件必须同时满足才能成立!
特点:有false则false (有一个不满足就不成立!)
&符号连接的左边表达式如果是false,右边依然要执行,效率低!
逻辑或|: 或的关系,只要满足一个条件即可成立
特点:有true,则true
|符号连接的左边表达式如果是true,右边依然要执行,效率低!
逻辑异或^
特点:相同则为false,不同则为true
简单记 男女关系
"男男" "女女" false
"女男" "男女" true
逻辑非!
特点:非true,则false
非false,则true
偶数个非是它本身!
扩展的逻辑运算符:逻辑双与&& 逻辑双或||
逻辑双与&&和逻辑单与&有什么区别?
共同点:有false,则false(并列条件,必须同时满足条件才成立!)
区别:逻辑单与&:连接的表达式左边如果是false,右边依然要执行
而逻辑双与&& ,连接的表达式如果左边是false,则右边不执行(具有短路效果)
开发中:并列条件逻辑双与&&代替逻辑单与&,因为效率高!
或的条件:优先采用是逻辑双||代替逻辑单或|,效率高!
逻辑双与||:左边为true(有true,则true),右边不执行,具有短路效果!
三元运算符(三目运算符)
还有二目:一个表达式两个变量 x==y
三元运算符的格式:
(表达式)? 执行true的结果:执行false的结果; (后期在jdk源码中会见到)
执行流程:
1)表达式可以简单可以复杂,结果是boolean,判断表达式是否成立
如果成立,则执行true的结果
2)否则不成立,则执行false的结果;
例题:
//定义两个变量
int a = 10 ;
int b = 12 ;
//求两个变量的最大值(没有明确要求数据类型默认int)
//格式:(表达式)? 执行true的结果:执行false的结果;
//定义一个变量max
int max = (a>b)?a:b; //符号:都是英文的
System.out.println("两个变量中的最大值是:"+max);
System.out.println("--------------------------------");
//求最小值
int min = (a
System.out.println("两个变量中的最小值是:"+min);
System.out.println("--------------------------------");
//比较a和b的值是否相等 true/false
//方式1:
boolean flag = (a==b)? true:false ;
System.out.println(flag) ;
//方式2:boolean flag = (a==b);
//需求:自定义三个变量,x,y,z(默认int),比较三个数据中的最大值;
int x = 10 ;
int y = 30 ;
int z = 20 ;
//三元运算符实现
//方式1:分步实现
//1)将x和y先进行比较,使用一个中间变量记录x和y最大值
//2)使用这个临时变量记录的最大值在和z比较
//(表达式)? 执行true的结果:执行false的结果;
//方式2:定义一个变量(中间变量)
int temp = (x>y)?x:y;
//定义结果变量max2
int max2 = (temp>z)? temp : z ;
System.out.println("三个数据中的最大值是:"+max2) ;
System.out.println("-----------------------------------------") ;
//三元运算符的嵌套方式(不推荐)
int max3 = (x>y)?((x>z)?x:z):((y>z)?y:z) ;
System.out.println("三个数据中的最大值是:"+max3) ;
位运算符:它是针对数据直接进行运算的!
基本的位运算符:
位与&:有0,则0
位或|:有1,则1
位异或^:相同则为0,不同则为1
反码~:所有的二进制位全部按位取反,0变1,1变0
程序:
class OperatorDemo{
public static void main(String[] args){
System.out.println(3&4) ;
System.out.println(3|4) ;
System.out.println(3 ^ 4) ;
System.out.println(~3) ;
}
}
图形解释:
位异或的应用
如何交换两个变量的数值?
程序
//定义两个变量
int a = 10 ;
int b = 20 ;
//方式1:中间变量(开发中常用)
int temp = a; // temp = 10
a = b ; // a = 20 ;
b = temp ; // b =10 ;
//方式2:位异或^特点:一个数据被另一个数据位异或两次,其值是它本身
a = a ^ b ;
b = a ^ b ; // a ^ b ^ b
a = a ^ b ; // a ^ b ^ a
<<(左移):
将"<<"左边的数据向左移动指定的位数(补码进行移动),将高位丢弃掉,空位补0
结论:将"<<"左边的数据乘以2的移动次幂
>>(右移):
将">>"左边的数据使用补码向右移动,如果最高符位是0,左边补0;如果最高符号位是1,左边补1;
结论:将">>"左边的数据除以2的移动次幂
>>>(无符号右移):
将">>>"左边的数据使用补码向右移动,无论最高符号位是1还是0,永远左边空位补0;
为什么要使用键盘录入数据呢?
如果直接去定义变量,直接写死了,程序不灵活,jdk提供给我们 "文本扫描器",可以键盘录入数据,让程序灵活一些 。
键盘录入数据的操作步骤:
1)在class类的上面书写导包的格式
固定格式: import java.util.Scanner;(在Java中只要不是java.lang包下的都需要导包)
2)在main方法中,创建文本扫描器 :格式
Scanner 文本扫描器变量名 = new Scanner(System.in) ; 固定格式
3)提示并录入数据(没有提示类型,默认录入int)
System.out.println("请输入一个数据:") ;
int 结果变量= 文本扫描器变量名.nextInt() ; nextInt():文本扫描器提供 录入int数据的方法
4)使用结果变量;
程序:
import java.util.Scanner ;
class ScannerDemo{
public static void main(String[] args){
//2)创建文本扫描器对象
Scanner sc = new Scanner(System.in) ;
//3)提示并录入数据(没有提示类型,默认录入int)
System.out.println("请您输入一个数据:") ;
int a = sc.nextInt() ;
//4)使用变量a
System.out.println("a的值是:"+a) ;
}
}
Java中流程语句有:顺序结构语句、选择结构语句、循环结构语句
顺序结构语句:从main方法这个入口进去,代码由上而下依次加载!
特例:
只要在main方法之前,jvm退出了!
jdk提供一个类System.exit(0) ;正常终止jvm(后面常用类中)
程序:
class ShunXuDemo{
public static void main(String[] args){
System.out.println("程序开始了...") ;
//System.exit(0) ; //终止jvm
System.out.println("我爱高圆圆...") ;
int x = 100 ;
System.out.println("helloworld"+x) ;
System.out.println("程序结束,over...") ;
}
}
三种格式:
格式1:if(条件表达式){
语句;
}
格式1的执行流程:
条件表达式成立,则执行语句,否则不执行;
if格式1应用场景:针对单个条件进行判断!
格式2:if(条件表达式){ (开发中使用居多的)
语句1;
}else{
语句2;
}
格式2的执行流程:
1)首先判断条件表达式是成立,如果成立,则执行语句1
2)否则,不成立,则执行语句2
注意:else后面不能带()
if语句格式2的一种嵌套格式
if(表达式1){
if(表达式2){
语句1;
}else{
语句2;
}
}else{
if(表达式3){
语句3;
}else{
语句4;
}
}
例题:键盘录入三个数据,获取三个数据中的最大值
*/
import java.util.Scanner ;
class IfDemo{
public static void main(String[] artgs){
//创建键盘录入数据
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请您输入第一个数据:") ;
int a = sc.nextInt() ;
System.out.println("请您输入第二个数据:") ;
int b = sc.nextInt() ;
System.out.println("请您输入第三个数据:") ;
int c = sc.nextInt() ;
//三元运算符
//中间变量
int temp = (a>b)?a:b ;
//定义结果变量接收数据
int max = (temp>c)?temp:c ;
System.out.println("三个数据最大值是:"+max) ;
System.out.println("------------------------------") ;
//if...else...嵌套
//定义一个结果变量max2
int max2 ;
if(a>b){
//a比b大
//嵌套if...else...
if(a>c){
//同时a比c大
max2 = a ;
}else{
//c大
max2 = c ;
}
}else{
//a比b小
//b和在c进行比较
if(b>c){
max2 = b;
}else{
max2 = c ;
}
}
//输出结果
System.out.println("三个数据最大值是:"+max2) ;
}
}
if...else...格式和三元运算符的区别?
三元运算符只是一个运算符号,不是流程控制语句,在三元中不能输出打印值,可以操作具体的数据值(结果最终是数据值);
而if...else...流程控制语句,范围远远大于三元运算符,既可以使用具体数据值,也可以是打印内容;
三元运算符能够使用的一定能够if...else...
if...else...能够实现的,不一定能够使用三元!
格式3:if(条件表达式1){
语句1;
}else if(条件表达式2){
语句2;
...
...
}else{
语句n;
}
格式3的执行流程:
1)先判断表达式1是否成立,成立,则执行语句1
2)不成立,则判断表达式2是否成立,成立,执行语句2;
否则依次...进行判断
...
3)如果上面都不成立,则执行else语句,最终结束;
例题:需求(默认int):
键盘录入月份的值,判断季节
3,4,5 春季
6,7,8 夏季
9,10,11 秋季
12,1,2 冬季
具体程序:
//导包
import java.util.Scanner ;
class IfTest{
public static void main(String[] args){
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请你输入一个月份的值:") ;
int month = sc.nextInt() ;
if(month<1 || month>12){
System.out.println("对不起,月份数据非法!") ;
}else if( month== 3 || month == 4 || month==5){
System.out.println("春季") ;
}else if(month == 6 || month == 7 || month == 8){
System.out.println("夏季") ;
}else if(month == 9 || month == 10 || month==11){
System.out.println("秋季") ;
}else{
System.out.println("冬季") ;
}
}
}
switch语句格式:
switch(表达式){
case 值1:
语句1;
break ;
case 值2:
语句2;
break ;
...
...
default:
语句n;
break ;
}
执行流程:
1)表达式中的值先和case值1比较,如果匹配,执行语句1,语句break,语句结束;
2)case值1不匹配,继续和case值2进行比较,如果一致,执行语句2,swich结束;
...
...
3)如果上面的case的值和表达式中的结果值都不匹配,执行default语句,
执行语句n,switch语句结束;
程序:
case的穿透作用
1) 在switch语句中先将数据和case中的数据进行比较,如果相同则执行对应的流程语句,然后通过break结束循环,如果都不匹配就进入default中,执行default的流程语句;
2) 如果数据匹配成功执行对应的流程语句,当该case中没有break语句结束循环,那么将不用匹配case中的值,继续向下运行,直到遇到break语句结束循环。
程序:
//导包
import java.util.Scanner ;
class SwitchTest2{
public static void main(String[] args){
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请您输入月份的值:") ;
int month = sc.nextInt() ;
//利用case穿透,简化代码
switch(month){
case 3:
case 4:
case 5:
System.out.println("春季") ;
break ;
case 6:
case 7:
case 8:
System.out.println("夏季") ;
break ;
case 9:
case 10:
case 11:
System.out.println("秋季") ;
break ;
case 1:
case 2:
case 12:
System.out.println("冬季") ;
break ;
default:
System.out.println("对不起,非法数据!地球没有该月份") ;
break ;
}}}
switch语句使用的注意事项:
1)case语句里面是有break,
如果没有书写break,会造成"case穿透"
2)case语句后面的值只能是常量值,不能是变量值
(Java是一个强类型语言:语法结构很严谨)
3)关于default语句
它可以在语句中的任何位置,不影响switch语句的执行流程!
但是如果在语句中,那么break不要省略!(考点)
如果default语句它在语句的末尾,break可以省略
4)switch语句的结束条件:
1)语句break结束
2)程序默认执行到末尾!(顺序结构语句都是依次由上而下,末尾结束!)
基本类型:byte,int,short,char
jdk5版本以后,表达式中值的类型可以是枚举 enum(属于引用类型)
jdk7版本以后,表达式中值的类型可以是String:字符串 (属于特殊的引用类型)
for(初始化语句;条件表达式;控制体语句或步长语句){
循环体语句;
}
执行流程:
1)先初始化语句进行赋值
2)判断条件表达式是否成立,如果成立,执行循环体语句
2.1)继续执行控制台语句或者步长语句 对初始化语句的变量进行自增或者自减
2.2)继续判断条件表达是否成立,如果成立,按照上面 这种方式执行;
2.3)如果变量自增或者自减到条件表达式不成立为止,循环语句结束!
程序:
class ForDemo{
public static void main(String[] args){
//原始的做法
System.out.println("helloworld") ;
System.out.println("helloworld") ;
System.out.println("helloworld") ;
System.out.println("helloworld") ;
System.out.println("helloworld") ;
System.out.println("--------------------------") ;
//上面代码冗余度大,优化
/*
for(初始化语句;条件表达式;控制体语句或步长语句){
循环体语句;
}
*/
for(int x = 1; x<=5 ; x++){//x=1,1<=5-->x=2,x<=5,x=3,x<=5,x=4,x<=5,x<=5,x=6,x<=5
System.out.println("helloworld") ;//第一次打印/第二次/第三次//第四次//第五次
}}}
基本格式:
while(条件表达式){
循环体语句;
控制体语句或者步长语句;
}
扩展格式:(使用多)
初始化语句:
while(条件表达式){
循环体语句;
控制体语句或者步长语句;
}
执行流程:
1)初始化语句进行变量赋值
2)判断条件表达式是否成立,
成立,执行循环体语句,依次执行控制体语句(对变量控制)
继续回到2)进行判断
...
...
3)条件表达式不满足,循环结束!
例题展示:
class WhileDemo{
public static void main(String[] args){
/*
初始化语句:
while(条件表达式){
循环体语句;
控制体语句或者步长语句; (必须存在,否则造成"死循环")
}
*/
int x = 1 ;
while(x <= 5){
System.out.println("helloworld") ;
x++ ;//控制体语句
}
}
}
共同点:
都是使用循环思想解决一些问题
不同点:
1)格式本身不同
①for(初始化语句;条件表达式;控制体语句){
循环体语句;
}
②初始化语句;
while(条件表达式){
循环体语句;
控制体语句;
}
2)是否明确循环次数
for循环:明确循环次数优先for循环,(for还是很频繁使用的)
while循环:不明确循环次数,使用while循环
3)从内存角度考虑销毁不同:
for循环结束,里面的变量及时释放了,所以不能在访问for中的变量
whlile循环结束,依然可以访问里面变量,
所以消耗资源相对for循环大一些!
格式:
初始化语句;
do{
循环体语句;
控制体语句;
}while(条件表达式) ;
执行流程:
1)初始化语句进行赋值
2)循环体语句,--->-完成条件判断---控制体语句
继续判断,当条件不满足,循环结束!
如果条件直接不满足,循环体至少执行一次;
这也是for/while最大的区别
dowhile 循环开发中很少使用这个格式 (jdk源码会用的!)
常见的两种死循环格式
①for(;;){//jdk源码中比较多
循环体...
}
②while(true){ //推荐
循环体...
}
利用死循环解决一些问题!
死循环:肯定需要利用一些条件,当达到某种条件的时候,结束循环(break;中断,结束!)
例题:
class WhileDemo3{
public static void main(String[] args){
/*
for(;;){
//逻辑:达到一种条件,break
System.out.println("今天很开心,学习了死循环!") ; //没有break语句会一直循环
}
*/
//第二种格式
while(true){
//逻辑:达到一种条件,break
System.out.println("今天很开心,学习了死循环!") ; //没有break语句会一直循环
}}}
格式:
for(初始化语句;条件表达式;控制体语句){
//循环体---就是内层for循环
for(初始化语句2;条件表达式2;控制体语句2){
内层循环的循环体...
}
}
详细分析:
例题1:当需要在dos控制台打印输出四行5列的*形时该怎么做?
*****
*****
*****
*****
程序:
class ForForDemo{
public static void main(String[] args){
//原始的做法:
//输出四句话:每一个*****
System.out.println("*****") ;
System.out.println("*****") ;
System.out.println("*****") ;
System.out.println("*****") ;
System.out.println("---------------------------------") ;
//第一行:有5个*,单独每次打印一个*,还不能换行,
//Sytem.out.print():不换行打印内容
/*
System.out.print("*") ;
System.out.print("*") ;
System.out.print("*") ;
System.out.print("*") ;
System.out.print("*") ;
*/
//上面这个代码每次打印一个*,冗余度大,循环改进
//循环5次
for(int x = 0 ; x<5;x++){//0,1,2,3,4
//循环体:
System.out.print("*") ;
}
//换行
System.out.println() ;
//第二行
//5个*,在进行换行
for(int x = 0 ; x < 5 ; x++){
//循环体
System.out.print("*") ;
}
//换行
System.out.println() ;
//第三行
//5个*,在进行换行
for(int x = 0 ; x < 5 ; x++){
//循环体
System.out.print("*") ;
}
//换行
System.out.println() ;
//第四行
//5个*,在进行换行
for(int x = 0 ; x < 5 ; x++){
//循环体
System.out.print("*") ;
}
//换行
System.out.println() ;
System.out.println("----------------最终版优化----------------") ;
//最终版的进行优化
/*
上面的这个代码 ,循环了四次,冗余度,进行优化
//5个*,在进行换行
for(int x = 0 ; x < 5 ; x++){
//循环体
System.out.print("*") ;
}
//换行
System.out.println() ;
*/
for(int x =0 ; x<4; x++){//x=0,1,2,3 x:行数
for(int y = 0 ; y < 5 ; y++){//y:列数 0,1,2,3,4
//循环体
System.out.print("*") ;
}
//换行
System.out.println() ;
}
}
}
例题2:
//需求打印
*
**
***
****
*****
分析:
定义变量x:行数 ,y,列数(从0开始)
x=0,第一行, 有1列 y= 0
x=1,第二行,有2列 y<=1
x=2,第三行,有3列 , y<=2 0,1,2
x=3,第四行,有4列, y<=3 0,1,2,3
x=4,第五行,有5列, y<=4 0,1,2,3,4
列数的变化y<=x
程序:
class ForForDemo2{
public static void main(String[] args){
//5行5列的*
for(int x = 0 ; x <5 ; x++) { //外层控制行数
for(int y = 0 ; y < 5 ;y++){ //控制列数
System.out.print("*") ;
}
System.out.println() ;
}
System.out.println("--------------------------") ;
//5行5列,列数在变化
for(int x = 0 ; x < 5 ; x++){//行数 x=0,0<5 ,1<5
for(int y = 0 ; y <=x ;y++){//变化的列数 y=0,y<=0 y=0,y<=1
System.out.print("*") ;//第一行一个*
}
System.out.println() ;//换行
}
}
}
例题3:打印9-9乘法表
class ForForDemo3{
public static void main(String[] args){
//99乘法表:列数y小于等于行数 (x)
//保证数据:x,y都是1开始
for(int x = 1 ; x <=9 ; x++){//行数 x=1 ,1<=9
for(int y = 1 ; y <=x ; y ++){//列数 y=1,y<=1
//1 * 1 = 1
// \x:x代表任意字符
//"\t" :制表符号 ,相当于tab键的效果
System.out.print(x+"*"+y+"="+(y * x)+"\t") ;
}
System.out.println() ;//换行
}
}
}
跳转控制语句:break、continue、return
break结束当前循环;continue是结束当前这次循环跳转到下一个循环;return是结束当前的方法
break语句
break:结束中断的意思
两种应用场景:
1)循环语句中使用,结束循环用的
2)switch语句中使用,结束switch
不能单独使用,不能脱离上面两种场景!
早期使用:break 标签名称; 结束指定的循环
在for循环嵌套中,给for循环的前面加上一个 "标签名称:"
wc:代表外层循环
nc:代表内层循环
wc:for(初始化语句;条件表达式;控制体语句){
nc:for(初始化语句2;条件表达式2;控制体语句2;){
//循环体;
//当达到我指定的条件,
break wc;//结束外层循环了
}
}
例题:
class BreakDemo{
public static void main(String[] args){
//break; 在 switch 或 loop 外部中断
for(int x = 1 ; x <=10 ; x++){
if(x == 3){
break ;//结束,中断
}
System.out.println(x) ;
}
System.out.println("-----------------------------") ;
wc:for(int x = 0 ; x < 5 ; x ++){//行数 //x=0 ,0<5,1<5
nc:for(int y = 0 ; y <6 ; y ++){//列数 y=0,0<6,1<6,2<6,3<6
/*
if(x==3){//四行
//break wc;//结束外层循环
}
*/
if(y==3){
break nc;
}
System.out.print("*") ; //***
//***
}
System.out.println();//换行
}
}
}
跳转语句continue
continue:继续执行(结束当前循环,立即进入下一次循环),不能单独使用
例题:
class ContinueDemo{
public static void main(String[] args){
//continue ; //continue 在 loop 外部 (仅仅在循环语句中使用)
for(int x = 1 ;x<=10;x++){
if(x==4){
//continue:继续执行(结束当前循环,立即进入下一次循环)
continue ;
}
System.out.println(x) ;//1235678910
}
}
}
跳转语句return
return :返回
很少单独去使用(不建议),后面一般都会有返回结果值;
return应用场景:
在Java中的方法(函数)中去使用,目的就是结束这个方法,并且还有返回结果;
什么是Java中的方法(函数)?
方法:就是一个代码块{},给{}起一个名字(方法名),然后方法中逻辑书写(根据你的实际需求)
以后见到同样一个功能代码块,直接调用方法名即可!
举例:
植物大战僵尸游戏---每一个关卡都有一个豌豆芽发射炮弹这个动作,这动作,可能需要100行代码,每一个关卡,都需要书写100行代码,所以干脆给100行代码---{}包裹起来,给它单独起一个名字,以后见到这种"豌豆芽发射炮弹"这个动作,直接调用这个"方法名",代码复用性就提高了!
Java中定义方法的格式:
public static 返回值类型 方法名(形式参数类型1 参数名1,形式参数类型2 参数名2...){
//完成方法的逻辑
return 结果;
}
解释上面这个格式:
前面固定public static (现在是在有main方法的类中书写方法需要加static)
返回值类型:也就是数据类型(现在研究的基本数类型)
方法名:就是满足标识符的命名规则:见名知意 (小驼峰命名法)
形式参数类型:也是数据类型(目前:基本数据类型)
参数名:就是变量名
有返回值类型的方法如何调用呢?
1)单独调用 ---方法名(实际参数列表) ; (有返回类型的方法不能使用)
2)输出调用 ---System.out.println(方法名(实际参数列表)) ;
输出调用:可以,写死了,如果相对结果值在进行操作,就不能用了
3)赋值调用:(推荐)
在书写方法时需要明确两点:
1)明确返回值类型
2)明确形式参数类型以及形式参数的个数
在Java中有返回值类型的方法的定义以及调用格式中注意事项:
1)方法和方法平级关系,不能在一个方法中去定义另一个方法!
2)定义方法的返回值类型和main方法中调用方法的时候,接收结果类型的不匹配!(需要一致)
3)Java是强类型语言,在定义的方法时候,
形式参数名前面必须有参数类型
4)必须有return语句,没有就会编译报错!
5)定义方法的时候,有{号地方不能有分号;有分号;,不能有{左大括号
例题:
class FunctionDemo2{
public static void main(String[] args){
//定义两个数据求和的方法
/*
//方法和方法平级关系,不能在一个方法中去定义另一个方法!
public static int sum(int a,int b){
}*/
//赋值调用
//接收也必须为int
//boolean result = sum(10,20) ;
int result = sum(10,20) ;
System.out.println(result) ;
}
//两个数据求和,返回是int
public static int sum(int a,int b){
//public static int sum(int a,int b);{ 没有意义这个方法,;代表语句结束!
// public static int sum( a,b){//形式参数名前面必须有参数类型
return a + b ;
}
}
有些需求,是直接要求将内容直接打印控制台,没有具体返回值,Java规定,当方法没有具体返回值的时候,需要使用"void"充当这个 "返回值类型"这个格式,没有返回值类型的方法体中{}里面,就应该直接打印或者完成一些其他业务(数据交互)...
没有具体返回值类型的方法的定义格式:(没有return语句)
public static void 方法名(参数类型1 参数名1,参数类型2 参数名2...){
//完成方法体逻辑
//输出内容....
}
调用方法:
1)赋值调用和输出调用都使用不了
2)推荐:单独调用
例题:
需求:使用方法来完成打印4行5列的*形
*****
*****
*****
*****
class FunctionDemo{
public static void main(String[] args){
//没有使用方法
for(int x = 0 ; x < 4 ; x++){
for(int y = 0 ; y < 5 ; y ++){
System.out.print("*") ;
}
System.out.println() ;
}
System.out.println("-----------使用方法改进上面的代码---------------") ;
//调用没有具体返回值的方法
//赋值调用
//void v = printStar(5,6); //void不是数据类型 (非法的表达式开始)
//输出调用 (错误使用)
//System.out.println(printStar(5,6)) ;
//单独调用
printStar(5,6) ;
}
//定义一个打印4行5列*的方法
/*
两个明确
1)明确返回值类型: void
2)明确参数类型以及参数个数
int类型,行数和列数2个参数
*/
public static void printStar(int m,int n){//m行数,n列数
for(int x = 0 ; x < m ; x++){
for(int y = 0 ; y < n ; y ++){
System.out.print("*") ;
}
System.out.println() ;
}
}
}
Java中规定:如果方法名相同,参数列表不同,与返回值无关---这一系列的方法都称为"方法重载 OverLoad"
参数列表不同:
1)参数个数不同
2)参数类型不同
3)考虑参数类型的先后顺序
例如:public static int sum(double a,int b){}
public static int sum(int a,double b){}
方法重载的意义:
重载的意义:提高功能扩展性(一个方法中可以传递任何类型参数)
为了提高这个方法的使用率,让这个方法在任何场景下都能用同一个方法,可以传递不同类型!
jdk提供大部分的工具:针对数学运算操作java.lang.Math--- 很多重载
abs(double a)
abs(float a)
abs(int a)...
形式参数问题: (现在研究基本类数据类型)
// jvm内存结构(栈,堆,方法区,本地方法区,pc寄存器(程序计数器)
class Demo{
public static void main(String[] args){
int a = 20 ;
System.out.println(a) ;//20
change(a) ;/*调用方法change()但该方法的形式参数是基本数据类型,形式参数的改变不会影响实际参数*/
System.out.println(a) ;//40 //20 /*第一个40是change中输出的,20是因为方法中形参的改变没有影响到main方法中的实际参数,所以a还是20*/
}
public static void change(int a){
a = 40 ;
System.out.println(a) ;/*上述的解释也可以这样理解:int a是一个局部变量,只会在change()这个方法中起作用,一旦方法结束,就立即清除变量a所赋的值*/
}
}
方法的形式参数如果是引用数据类型(数组,类,接口),形式参数的改变会直接影响实际参数
String类:字符串,它是一个特殊的引用类型,它作为形式参数传递,和基本类型作为形式参数效果一致!
给员工发工资,有60个员工,按照目前说,只能定义60个变量,分别去赋值,显的非常麻烦;
Java提供一种容器--->可以存储同一种类型的元素--->数组
数组:必须满足这些元素数据类型必须是同一种类型!
数组定义以及初始化
定义格式:
1)数据类型[] 数组名称;
2)数据类型 数组名称[] ;
举例:
int[] arr; 定义一个int类型的数组arr
int arr[] ; 定义一个int类型的arr数组
初始化:
1)动态初始化
给定数组长度,系统(jvm)默认分配数组元素内容;
格式:
数据类型[] 数组名称 = new 数据类型[数组长度] ;
数据类型 数组名称[] = new 数据类型[数组长度] ;
举例:
int[] arr = new int[3] ;
在数组如何确定元素的内容?数组名称[索引值(角标值)]:从0开始
2)静态初始化
原本格式:
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,元素3....} ;
数据类型 数组名称[] = new 数据类型[]{元素1,元素2,元素3....} ;
简写格式
数据类型[] 数组名称 ={元素1,元素2,元素3....} ;
数据类型 数组名称[] = {元素1,元素2,元素3....} ;
举例:
int[] arr = {1,2,3} ;
arr[0] = 1 ;
arr[1] = 2 ;
arr[2] = 3 ;
注意事项:
不能既动态初始化,又静态初始化(动静结合)
int[] arr = new int[3]{1,2,3} ;//错误
暂缓数组,后面补充(形参是引用数据类型、遍历、冒泡、最值、数组的图形解释、jvm内存结构的分配)后面稀碎,待补充
面向过程代表--->C语言
1)需求分析 --- 键盘录入三个数据,比较数据中最大值---->使用方法完成
2)定义方法---分析返回值/参数类型/有几个参数
3)返回结果
4)自己在main方法测试
最大特点:自己始终执行者
举例:生活中的例子
面向过程:买电脑
看配置(喜欢的)---->去赛格电脑城--->砍价还价---->买回来电脑
洗衣服:
脏衣服---->找一个盆--->接水--->泡一泡---->搓一搓---->拧一拧----->晾衣服
买菜
去菜市场---->砍价/还价---->买菜回来
面向对象:买电脑
看喜欢的配置---->找一个懂行的朋友---->买回来电脑
洗衣服:
脏衣服---->找一个全自动洗衣机---->晾衣服
买菜:
找一个"对象"--->买菜回来
面向对象思想特点:
1)更符合生活中的思想行为习惯!
2)让复杂的事情简单化!
3)让我们从执行者变成指挥者!(角色变化)
面向对象设计理念/特征
不断去创建对象,指挥对象做事情!
面向对象的特征:封装、继承、多态
将大象装进冰箱 面向过程分析
//伪代码
//面向过程:
class Demo{
public static void main(String[] args){
open() ;
in();
close() ;
}
//分析:冰箱开的方法
public static void open(){
System.out.println("打开冰箱门") ;
}
//分析:将大象装进去的方法
public static void in(){
System.out.println("将大象装进冰箱") ;
}
//分析:将冰箱门关闭
public static void close(){
System.out.println("关闭冰箱门") ;
}
}
将大象装进冰箱(面对对象的方式分析)
//UML:名词提取法:分析:有几个名词---->使用"类"来定义,分析:这个类与哪些功能?
//大象---大象事物-----> class 大象类{}
//冰箱---冰箱事物---->class 冰箱类{}
//Demo类 测试类 (有main方法类)
//伪代码
class Demo{
public static void main(String[] args){
//使用Java面向对象中创建类对象的格式
//创建冰箱类对象
//使用冰箱类对象调用开门的方法 open() ;
//创建大象类对象
// 使用大象类对象调用in方法 in();
// 调用冰箱类的关门的方法 close() ;
}
}
//大象类--->进去的方法
class 大象类{
public static void in(){
System.out.println("大象进去了") ;
}
}
//冰箱类---->开/关
class 冰箱类{
public static void open(){
System.out.println("打开冰箱门") ;
}
public static void close(){
System.out.println("关闭冰箱门");
}
}
类: (是Java中最基本单元)
类是描述现实世界"事物"的一组"属性"和"行为"的集合!
类和事物: 一一对应,相辅相成!
一个事务------>定义一个类
具体事物-----代码中体现--------->创建一个对象
创建对象的格式:
类名 对象名 = new 类名() ;
对象名.成员变量名 = 值; (跟成员变量类型一致);
对象名.方法名() ;调用方法,展示这个具体事物有什么功能
例题:
使用Java代码描述一个学生事物
学生事物
属性:姓名,年龄,性别...
行为:学习
代码中体现出来----定义一个学生类
成员变量(类中,方法外)---就是描述现实世界事物的属性
成员方法(非静态):和定义方法格式一样,(去掉了static)
类:描述现实世界事物的一组属性和行为的集合!
*/
//学生类
class Student{
//成员变量(属性):类中,方法外
String name ; //姓名
int age ; //年龄
String gender ; //性别
//成员方法---->学生的行为:学习
public void study(){
System.out.println("good good study,day day up!!") ;
}
//带一个返回值String
public String playGame(String gameName){//玩的游戏名字 "csgo"
return "学习累了,可以玩会"+gameName ;
}
}
//测试类---main方法所在类的类
class StudentDemo{
public static void main(String[] args){
/*
具体事物-----代码中体现--------->创建一个对象
创建对象的格式:
类名 对象名 = new 类名() ;
对象名.成员变量名 = 值; (跟成员变量类型一致);
对象名.方法名() ;调用方法,展示这个具体事物有什么功能
//代码中:描述---这个学生的叫 "高圆圆"
//年龄 44
//性别 女
*/
//创建学生类对象
//类名 对象名 = new 类名() ;
Student s = new Student() ;
//成员变量赋值: name,age,gender
// 对象名.成员变量名 = 值;
s.name = "高圆圆" ;
s.age = 44 ;
s.gender = "女";
System.out.println("该学生的姓名是:"+s.name+",年龄是:"
+s.age+",性别是:"+s.gender) ;
//体现学生的行为(调用成员方法)
s.study();
//public String playGame(String gameName){
String result = s.playGame("csgo") ;
System.out.println(result) ;
}
}
需求:
定义一个学生类,描述这个学生事物的属性:姓名,年龄
学生行为:学习
方便打印学生信息--->提供show()展示姓名和年龄
按上面的需求:进行测试
发现问题:如果在测试类中给年龄赋值非法数据,依然打印;
优化方案1:在学生类中定义一个成员方法(非静态),给年龄赋值(加入逻辑判断)
可以去解决,但是不调用这个方法,依然使用 对象名.age = 非法数据;
方案2:
java提供另一种技术
封装
将一个事物的属性私有化(对外界隐藏,private)--->保证数据的安全性
对外提供公共的成员访问方法:setXXX(传参)/getXXX(),来对成员属性进行操作!
以后在书写 事物(对应的类:手机类/用户类等等,只要描述它的属性和行为)
成员变量(属性)---->全部私有化!
*/
//定义一个学生类
class Student{
String name ; //姓名
private int age ; //年龄
//方便打印学生信息--->提供show()展示姓名和年龄
public void show(){
System.out.println("这个学生的姓名是:"+name+",年龄是:"+age) ;
}
//给年龄赋值的方法,并且加入逻辑判断
public void setAge(int a){ //a就是传入的年龄值
if(a<0 || a >150){
System.out.println("对不起,年龄非法!") ;
}else{
age = a ;//年龄赋值
}
}
}
//测试类
class StudentDemo{
public static void main(String[] args){
//创建一个学生对象(具体事物)
Student s = new Student() ;
//s.show() ;
s.name = "高圆圆" ;
s.age = 44 ; //age已经被private私有控制了
s.show() ;
System.out.println("------------------------------------") ;
//在创建一个学生对象(新的具体事物)
Student s2 = new Student() ;
s2.name = "赵又廷" ;
//s2.age = -45 ;//外界类将它年龄赋值为非法数据!
//访问setAge()方法
//s2.setAge(-45) ;
//不调用自定义的给年龄赋值的方法,依然可以直接访问age,赋值一个非法数据
s2.age = -1 ;
s2.show() ;
}
}
private关键字的特点:
1)被private修饰的成员变量/成员方法(非静态),只能在本类中访问,外界类不能访问!
2)虽然被私有修饰的成员变量以及成员方法(非静态)不能直接访问,但是都可以间接的通过"public"公共访问访问!
Java提供了一个关键字:(局部变量名称隐藏了成员变量名称)this--->代表当前类的对象的地址值引用!
格式:this.成员变量名 = 局部变量名;
区别:
1)类中的书写位置不同
成员变量:在类中,方法外
局部变量:在方法定义中或者方法声明上
2)jvm内存位置不同
成员变量:在堆内存中
局部变量:在栈内存中
3)生命周期不同:
成员变量:随着对象的创建而存在,随着对象的创建完毕并且使用完
等待垃圾回收器回收(不会立即回收)而消失!
局部变量:随着方法调用而存在,随着方法调用结束而消失
4)初始化值不同:
成员变量:存在系统默认初始化,也可以显示初始化
局部变量:总之:在使用局部变量之前,必须赋值,不赋值不行!
什么是构造方法?
1)方法名和类名一致
2)没有具体返回值类型
3)连void都没有
构造方法是可以重载!
构造方法的作用:
给类的成员进行数据初始化!
注意事项:
1)一个类中,如果没有任何构造方法,那么系统(jvm)自动会给我们提供无参构造方法!
2)一个类中,只提供有参构造方法,那么系统不会无参构造方法,此时,建议我们永远给出无参构造方法!否则,就出现问题!