04Java语言基础.docx
《04Java语言基础.docx》由会员分享,可在线阅读,更多相关《04Java语言基础.docx(19页珍藏版)》请在冰豆网上搜索。
![04Java语言基础.docx](https://file1.bdocx.com/fileroot1/2023-1/31/acb61272-b025-4cce-b038-dc9761f3ef86/acb61272-b025-4cce-b038-dc9761f3ef861.gif)
04Java语言基础
Java语言基础
学习完本章后,你应该知道并掌握:
⏹源文件布局
⏹内存模型
⏹数据类型
⏹标识符、关键字
⏹语句与表达式
⏹流程控制
⏹运算符
⏹值传递
⏹访问控制
4.1概述
本章主要讲解Java语言的语法,万丈高楼平地起,如果打的地基不牢,修的越高越容易倒塌。
这个道理依然适用于我们学习的过程,所以在开始后续学习之前,我们就必须把Java的语法搞清楚。
4.2任务分析
本章按照以“知识点切入”的方式来组织内容,每个同学要完成工作任务一节列出的所有任务。
时间:
12课时
4.3相关知识
程序结构,C语言基础,变量,内存,流程控制等;
4.4工作任务
4.4.1文件布局
新建train的Java工程,新建TestExample类,代码如下:
packagecom.hwadee.train.grammar;
importjava.lang.System;
classExample{
privateinti=1;
publicvoidfirstMethod(){
inti=4,j=5;
this.i=i+j;
secondMethod(7);
}
publicvoidsecondMethod(inti){
intj=8;
this.i=i+j;
System.out.println(this.i);
}
}
publicclassTestExample{
publicstaticvoidmain(String[]args){
Examplee=newExample();
e.firstMethod();
}
}
1、源文件布局
从TestExample的源码我们要得出以下结论:
源文件从上到下是包声明语句,如果这个类中要用到其他类使用import语句,接下来是类的申明;注意以下规则:
Ø源文件中可以申明多个类,但是生成的class文件是分开的;
Ø源文件中有且只能有一个public类,且类名是和源文件名是一致的;
Ø编译和执行时在类路径中会默认加入java.lang包下的类;
Øimport语句可以导入包下的所有类(但不包含子包),也可单独导入一个类;
Ø一个类中含有一个main方法,这个类就构成了一个应用,可以用java命令运行它,main方法是一个应用的入口;
2、命名规范
Ø包名是文件存放的目录,常以org、com开头,接下来是“机构(公司名).项目名.模块名”,采用小写形式
Ø类名代表一种类型,常采用名词,比如:
人、动物、电脑、食品、学生、老师等,采用首写字母大写其于小写的形式,一个类如果由多个单词组成,单词首字母都大写
Ø变量代表存放数据的单元,采用首字母小写的形式
Ø方法代表对象的行为,常采用动词,采用首字母小写的形式
3、类结构
class{
[]
[]
[]
}
图4.4.1类结构图
从上面的代码可以看出一个类是由属性、构造器、方法组成的,类是Java编程的基本单元;每个类都由一对大括号标记类的开始和结束,括起来的部分称为“类体”;Java程序员的职责就是设计类然后创建对象并调用,让程序按照预期结果运行下去;
4、属性
图4.4.2类属性
类中的每个属性声明都应该具有3个要素:
访问限定+变量类型+变量名;
5、方法
([argument_list]){
[statements]
}
图4.4.2类方法
每个方法都由一对大括号标记类的开始和结束,括起来的部分称为“方法体”,每个方法都应该具有例子中的基本结构;
4.4.2内存模型
1、内存模型
图4.4.1JVM内存模型
Øheap:
存放对象成员变量的数据,好比宾馆房间
Øjavastacks:
存放方法局部变量的数据,好比服务台
Ømethodarea:
存放字节码的区域
对于大家来讲这3个部分是要搞清楚的,其他的如果有兴趣可以深入研究;在“对象初始化”一节中我们将从对象创建开始进行分析这3部分的作用;
2、对象初始化
创建对象时到底发生了什么以及内存中有什么变化?
我想这是所有学习Java的人应该要搞清楚的事情,我们把对象创建过程称为对象创建“四步曲”:
Ø分配内存、成员变量默认初始化
Ø成员变量显示始化
Ø构造方法被调用
Ø引用变量被赋值
接下来分析TestExample类的main方法中的代码:
Examplee=newExample();以后在内存中的变化如下图:
图4.4.2内存模型
第一步:
栈内存单元“e”开辟,但没有值(问号表示)
第二步:
堆内存开辟,成员变量“i”默认初值是为0(初值取决于变量类型:
整型为0;浮点为0.0;布尔为false;字符为\u0000;引用类型为null)
第三步:
成员变量“i”显示赋值为1
第四步:
栈单元格被赋值
3、方法调用
当e.firstMethod()方法执行时,内存模型图如下所示:
图4.4.3方法调用内存模型
Ø局部变量(形参和方法内部申明的变量)是在栈中开辟的,又名临时变量、本地变量、栈变量
Ø成员变量是在堆中开辟的,又名实例变量;
Ø方法中的局部变量各自属于自己的方法,互不影响,所以可以重名
Ø堆区和栈区只存放了变量的数据
Ø从上图可以看出每个非静态方法内部都有一个this指针指向对象本身,我们知道这类方法的调用是要通过对象句柄,所以可以这样理解“谁调用此方法,this指针就指向谁”
Ø当方法被调用时形参变量就会开辟出来用以存放调用者传递过来的实参,如上例中firstMethod方法中调用secondMethod(7),7是实参,调用secondMethod(inti)方法时i就会开辟出来存放7,这个过程称为“方法调用过程”如上图所示
4.4.3数据类型
Java的数据类型分类两大类:
基本类型和引用类型,具体类型见下图所示:
图4.4.1Java数据类型
Ø变量申明与赋值:
publicclassAssignTest{
privatebyteb=1;
privateshorts=2;
privateinti=3;
privatelongl=4;
privatefloatf=1.2f;
privatedoubled=3.1415D;
privatecharc;
privatebooleanbl=true;
publicstaticvoidmain(String[]args){
AssignTestas=newAssignTest();
System.out.println(as.b);
System.out.println(as.s);
System.out.println(as.i);
System.out.println(as.l);
System.out.println(as.f);
System.out.println(as.d);
System.out.println((int)as.c);
System.out.println(as.bl);
}
}
图AssignTest反编图
整数的字面量默认是int类型,浮点字面量默认是double类型的,按照这样的理解,上例中我们有时可能会产生疑问,privatebyteb=1为何没问题,而privatefloatf=1.2为何不加f就有问题,1在byte表示的范围,1.2也在float表示的范围啊?
如果我们分析一下这个类的字节码就可以理解这个问题了。
对于byteb=1虚拟机会判断整数的大小,对于[0,5]之间的数都有对应的指令,所以这种情况分别执行两条指令:
iconst_1、istore_1,对于[6,127]的数会把这些数放在常量池,然后调用bipush(扩展成int值)入栈,再调用istore出栈;对于[128,32767]之间的数,会调用sipush(扩展成int值)入栈,再调用istore出栈;对于(32767,)之间的数将放在常量池,然后通过ldc,ldc2_w入栈,出栈时分别对应到istore,和lstore指令;对于浮点数有fconst_0、fconst_1、fconst_2,dconst_0、dconst_1超过了的数都放在常量池中然后通过ldc,ldc2_w入栈,出栈通过指令fstore、dstore指令进行。
所以象byteb=1;编译时会调用iconst_1、istore完成赋值,floatf=1.2如果允许的话默认调用ldc2_w入栈,然后调用fstore出栈这样就矛盾了(不兼容)。
Ø源码:
一个整数,按照绝对值大小转换成的二进制数,称为原码
Ø反码:
按位取反
Ø补码:
反码加1
正数的源码、反码、补码相同,负数是以补码表示
Ø计算-5的二进制表示:
源码:
00000101
反码:
11111010
补码:
11111011
Ø计算-128的二进制表示:
源码:
10000000
反码:
01111111
补码:
10000000
Ø一个整数的二进制表示方法:
publicstaticvoidprintBinaryInt(inti){
for(intj=7;j>=0;j--){
if(((1<=0)
System.out.print("1");
else
System.out.print("0");
}
System.out.println();
}
Ø变量赋值需注意
1.可以给char赋整数,比如:
charc=97表示“a”,因为全世界的文字都会对应到一个整数,也可以是unicode字符,比如:
charc=“\u0000”
2.可以给整型赋2进制、8进制、16进制,比如:
inti=077、inti=0xAB,8、16进制转为10进制和2进制转为10进制是一样的方法,比如:
0xAB=10*161+11*160=171,如果是10进制转为16进制可以先将10进制转为2进制,再将2过制转为16进制,比如:
将171转为16进制,先转2进制:
1010101,这个2进制对应的16进制是:
AB
3.可以给浮点按科学计数法赋值,比如:
doublef=3E2结果是300.0,但是整数不能用科学计数法;
Ø基本类型的包装类
基本类型
包装类
byte
Integer
short
Short
int
Integer
long
Long
float
Float
double
Double
char
Character
boolean
Boolean
4.4.4标识符
我们在写包名、类名、变量名、方法名时要采用合法的名称,不能使用Java保留的名称和不符合规定的名称。
合法的名称是指:
以Unicode字母、美元符、下划线开头,对之后的字符没有限制,同时大小写敏感谢,也没有长度的限定。
4.4.5保留字
4.4.6语句与表达式
Ø表达式:
表达式是由操作数、操作运算符组成的,根据优先级、结合方向和数据类型转换的约定进行求值运算,目的是为了说明某个计算过程。
例如:
1+1、2+3*4/5都是表达式,表达式经过运算是有结果的,而结果肯定是有类型的,所以表达式是有结果类型的,象1+1、2+3*4/5结果都是int类型。
一个复杂表式的运算优先级如果比较难于确定,可以通过小括号显示的表示出来,例如:
2+((3*4)/5),而小括号具有最高的优先级,如果存在嵌套,从里到外执行,所以上例中先执行3*4结果为12,再执行12/5结果为2,最后执行2+2,最终结果为4
Ø语句:
表达式后加上分号,就是语句了;
4.4.7流程控制
Ø循环
类型
语法
运用场景
示例
for
for(init_expr;booleantest_expr;alter_expr){
statementorblock;
}
一般用于循环次数明确的情况,示例程序明确循环10次
for(inti=0;i<10;i++){
System.out.println(“Hello!
”);
}
while
while(booleantest){
statementorblock;
}
一般用于循环次数不明确的情况,示例程序循环次数取次于用户的输入
intdata=System.in.read();
while(data!
=‘q’){
System.out.println(data);
data=System.in.read();
}
dowhile
do{
statementorblock
}while(booleantest);
先执行循环体,如果条件满足了会再次执行
Ø判断
类型
语法
示例
ifelse
if(booleanexpr){
statementorblock;
}else{
statementorblock;
}
intage=8;
if(age<12){
System.out.println(“少年”);
}else{
System.out.println(“非少年”);
}
if
if(booleanexpr){
statementorblock;
}
intage=70;
if(age>65){
System.out.println(“老年”);
}
ifelseifelse
if(booleanexpr){
}elseif(booleanexpr){
}else{
}
intage=8;
if(age<12){
System.out.println(“少年”);
}elseif(age<18){
System.out.println(“青少年”);
}else{
System.out.println(“不是青少年!
”);
}
switch
switch(intexpr){
caseconstant1:
{
statementorblock;
break;
}
caseconstant1:
{
statementorblock;
break;
}
default:
{
statementorblock;
}
}
charcolor=‘r’;
switch(color){
case‘r’:
{
System.out.println(“red”);
break;
}
case‘g’:
{
System.out.println(“green”);
break;
}
case‘b’:
{
System.out.println(“black’”);
break;
}
}
在学习循环的时候,重点是循环的初始值的确定和循环的进入条件,如果要能准确的找到初值和进入条件,一定要把问题描述清楚,画流程图是一种方式;
Ø跳转语句
类型
语法
运用场景
示例
break
break;
从循环中跳出或从判断中跳出
for(inti=0;i<10;i++){
if(i==5){break;}
System.out.println(“i==”+i);
}
continue
continue;
结束本次循环,开始下一次循环
for(inti=0;i<10;i++){
if(i==5){continue;}
System.out.println(“i==”+i);
}
return
return或returnvalue;
从方法中返回,前者不返回值,后者会给调用者返回值
publicvoidfirstMethod(){
……
return;
}
publicintadd(inti,intj){
returni+j;
}
4.4.8运算符
Ø算术运算符:
+-*/%++--
Ø逻辑运算符:
&&||!
Ø关系运算符:
><==>=<=!
=
Ø位运算符:
<<>>>>>&|~^
Ø条件运算符:
?
:
Ø赋值符号:
=+=-=*=/=
Ø实例运算符:
instanceof
Ø成员访问符:
.
Ø数组运算符:
[]
Ø优先级及类型转型操作符:
()
以上运算符根据需要的运算数的个数,也可以称为一元、二元、三元运算符
4.4.9值传递
packagecom.hwadee.train.grammar;
importjava.io.IOException;
classMyDate{
privateintday;
privateintmonth;
privateintyear;
publicMyDate(intday,intmonth,intyear){
this.day=day;
this.month=month;
this.year=year;
}
publicvoidprint(){
System.out.println(year+"-"+month+"-"+day);
}
publicvoidsetDay(intday){
this.day=day;
}
}
publicclassPassTest{
publicstaticvoidchangeInt(intvalue){
value=10;
}
publicstaticvoidchangeRef(MyDateref){
ref=newMyDate(1,1,2013);
}
publicstaticvoidchangeAttribute(MyDateref){
ref.setDay(4);
}
publicstaticvoidmain(String[]args)throwsIOException{
intvalue=20;
changeInt(value);
System.out.println(value);
MyDatedate=newMyDate(31,12,2012);
changeRef(date);
date.print();
changeAttribute(date);
date.print();
}
}
Ø引用类型变量单元中存放的是地址,基本类型变量单元中存放的是字面值
Ø无论是引用还是基本类型的传递依然遵守“方法调用过程”规则
4.4.10访问控制
所谓访问控制是指类的设计者为了控制调用者对类中的成员(成员变量、成员方法)访问而采取的一种限制访问策略;
classEmployee{
publicStringname;
privateintage;
Datebirthdate;
protecteddoublesalary;
}
publicclassEmployer{
}
john只能访问mary对象的public成员,tom和mary是“朋友”的意思是指它们位于同一包中(在一上圈子里),所以可以访问mary对象的protected成员和没有加访问限定的(default)成员,综上所述,归纳为以下几点:
Ø设计private成员的目的就是不提供给外界访问
Ø设计public成员的目的就是要提供给外部调用
Ø设计defulat成员只希望朋友访问(同包)
Ø设计protected成员的目的是希望子类或朋友访问
表4.10.1访问度
Modifier
SameClass
SamePackage
Subclass
Universe
private
Yes
default
Yes
Yes
protected
Yes
Yes
Yes
public
Yes
Yes
Yes
Yes
从上表可以看出,public成员允许所有人访问,private成员只允许在本类中使用,如果只想让子类及朋友类访问的可以使用protoected,只想让朋友类访问可以不加访问控制,采用默认,才开始接触访问控制时,可以将成员变量都加上private,要提供给外部调用的成员方法都加public
4.5归纳总结
本章详细讲解了Java语法,对于Java的学习首先要掌握语法没有问题,这就好比我们做游戏,首先你要了解游戏规则。
所以大家一定要搞清楚本章所涉及到的Java的基本语法,如果有问题的情况下建议不要开始后续章节。
4.6拓展提高
4.7练习与实训
练习:
1、堆栈的作用?
2、Java数据类型有哪些?
3、语句和表达式有何区别?
4、什么是访问控制?
5、方法调用过程是怎样调用的?
6、什么是对象创建“四步曲”?
实训:
1.完成文档中所有的例子。
2.画出方TestExample例子中的内存模型图。
3.画出PassTest例子中的内存模型图。
4.列举自己身边的10类对象,并写出对象具有的主要属性和方法。
5.在控制台打印:
*
**
***
****
*****
6.求阶乘
一个数X的阶乘(通常记作X!
)等于X*(X-1)*(X-2)……*1。
例如
4!
等于4×3×2×1=24。
创建一个称作Factor的应用程序,利用该应用程序可打印2,
4,6和10的阶乘。
7.猴子分桃
五只猴子来到一棵桃树前,它们将树上的桃子全部摘下放在一起,到了晚上,第一只猴子起来口渴了吃了一个,然后将桃子分为五堆,它把自己的那堆放好后将其他4堆合成一堆就睡了,然后第二只猴子,第三只,第四只,第五只猴子也这样做,请问树上至少有多少桃子?
8.Hanoi塔问题
设a,b,c是3个塔座。
开始时,在塔座a上有一叠共n个圆盘,这些圆盘自下而上,由大到小地叠在一起。
各圆盘从小到大编号为1,2,…,n,现要求将塔座a上的这一叠圆盘移到塔座b上,并仍按同样顺序叠置。
在移动圆盘时应遵守以下移动规则:
规则1:
每次只能移动1个圆盘;
规则2:
任何时刻都不允许将较大的圆盘压在较小的圆盘之上;
规则3:
在满足移动规则1和2的前提下,可将圆盘移至a,b,c中任一塔座上
图4.7.1Hanoi问题