JAVA第一阶段CentKiller

------------------------------------------------------------------------------

一、java概述

1、Java技术体系平台

JavaSE(JavaStandardEdition)标准版

支持面向桌面级应用(如Windows下的应用程序)的Java平台,提供了完整的Java核心API,此版本以前称为J2SE

JavaEE(JavaEnterpriseEdition)企业版

是为开发企业环境下的应用程序提供的一套解决方案。该技术体系中包含的技术如:Servlet、Jsp等,主要针对于Web应用程序开发,版本以前称为J2EE,学习javaEE是要以javaSE为基础的

JavaME(JavaMicroEdition)小型版

支持Java程序运行在移动终端((手机、PDA)上的平台,对JavaAPI有所精简,并加入对移动终端的支持,此版本以前称为J2ME

2、java虚拟机

JVM是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在JDK中

对于不同的平台,有不同的虚拟机,Java虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,到处运行”,所以才说java的跨平台性极好

3、JDK与JRE

JDK的全称(JavaDevelopmentKitJava开发工具包)

JDK=JRE+java的开发工具[java,javac,javadoc,javap等]

JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。

JRE的全称(JavaRuntimeEnvironmentJava运行环境)

JRE=JVM+Java的核心类库[类]

包括Java虚拟机(JVMJavaVirtualMachine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

JDK、JRE和JVM的包含关系

①JDK=JRE+开发工具集(例如Javac,java编译工具等)

②JRE=JVM+JavaSE标准类库(java核心类库)

③如果只想运行开发好的.class文件只需要JRE

4、下载安装JDK

安装完之后需要配置环境变量

环境变量原理:当前执行的程序在当前目录下如果不存在,win10系统会在系统中已有的一个名为path的环境变量指定的目录中查找。如果仍未找到,会出现错误提示

所以需要将java用到的程序路径存入到环境变量中去

centos安装java11

卸载安装的java

查看安装的目录,并设置JAVA_HOME

java-11的安装本地目录为:/usr/lib/jvm/java-11-openjdk-11.0.15.0.9-2.el7_9.x86_64/

添加环境变量,设置设置JAVA_HOME

vi/etc/profile在文件最后添加以下代码

source/etc/profile#刷新profile文件5、java快速入门

6、java开发注意事项

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

2>Java应用程序的执行入口是main()方法。

它有固定的书写格式:

publicstaticvoidmain(String[]args){...}3>Java语言严格区分大小写

4>Java方法由一条条语句构成,每个语句以“;”结束

5>大括号都是成对出现的,缺一不可,要习惯先写{}再写代码

6>一个源文件中最多只能有一个public类,其它类的个数不限

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

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

7、如何快速掌握新技术

二、转义字符

\t#一个制表位,实现对齐的功能\n#换行符\\#输出一个\\"#输出一个"\'#输出一个'\r#一个回车示例

代码注释分为javadoc注释和单行/多行注释

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

javadoc-d文件夹名-author-versionchar.javajava开发简单规范

1、类、方法的注释,要以javadoc的方式来写注释

2、非Javadoc的注释,往往是给代码的维护者看的,着重告述读者为什么这样写,如何修改,注意什么问题等(单行,多行注释)

3、使用tab操作,实现缩进,默认整体向右边移动;用shift+tab整体向左移

4、运算符和=两边习惯性各加一个空格。比如:2+4*5+345-89

5、源文件使用utf-8编码

6、行宽度不要超过80字符

7、代码编写次行风格和行尾风格,推荐使用行尾风格

三、变量

变量是程序的基本组成单位,变量有三个基本要素(类型+名称+值),变量相当于内存中一个数据存储空间的表示

classvariable{publicstaticvoidmain(String[]args){//定义变量先intc;//再给变量赋值c=9527;System.out.println(9527);//还可以定义变量和赋值一步到位inta=1;System.out.println(a+c);}}变量使用注意事项

1、变量表示内存中的一个存储区域,不同的变量,类型不同,占用的空间大小不同

2、该区域有自己的名称[变量名]和类型[数据类型]

4、该区域的数据/值可以在同一类型范围内不断变化

5、变量在同一个作用域内不能重名

6、变量=变量名+值+数据类型,即变量三要素

程序中+号的使用

1、当左右两边都是数值型时,则做加法运算

2、当左右两边有一方为字符串,则做拼接运算

3、运算顺序从左到右

classplus{publicstaticvoidmain(String[]args){System.out.println(100+98);//198System.out.println("100"+98);//10098System.out.println(100+98+"hello");//198helloSystem.out.println("hello"+100+98);//hello10098}}四、数据类型

每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(字节)

1、整型的使用细节

1>Java各整数类型有固定的范围和字段长度,不受具体OS[操作系统]的影响,以保证java程序的可移植性

4>bit:计算机中的最小存储单位;byte:计算机中基本存储单元,1byte=8bit

2、浮点类型

Java的浮点类型可以表示一个小数,比如123.4、7.8、0.12等等

1>单精度与双精度的区别

在内存中占有的字节数不同:单精度浮点数在机内占4个字节,双精度浮点数在机内占8个字节;

有效数字位数不同:单精度浮点数有效数字8位,双精度浮点数有效数字16位。

关于浮点数在机器中存放形式的简单说明:浮点数=符号位+指数位+尾数位,尾数部分可能丢失,造成精度损失(小数都是近似值)

2>使用细节

与整数类型类似,Java浮点类型也有固定的范围和字段长度,不受具体OS的影响。[float4个字节、double是8个字节]

classfolat_test{publicstaticvoidmain(String[]args){floatn=3.14F;doublem=3.14;System.out.println(n+"--"+m);}}3>浮点型常量有两种表示形式

十进制数形式,如:5.12、512.0f、.512(必须有小数点)

科学计数法形式,如:5.12e2[5.12*10的2次方]、5.12E-2[5.12/10的2次方]

4>通常情况下,应该使用double型,因为它比float型更精确

5>浮点数使用陷阱:2.7和8.1/3比较

所以得到一个重要的使用点:当我们对运算结果是小数的进行相等判断时,要小心,应该是以两个数的差值的绝对值,在某个精度范围类判断

但如果是直接查询得的小数或者直接赋值,则可以直接判断相等

classtrap{publicstaticvoidmain(String[]args){doublenum1=2.7;doublenum2=8.1/3;if(Math.abs(num1-num2)<0.00001){System.out.println("相等");}}}3、JavaAPI文档

2>Java语言提供了大量的基础类,因此Oracle公司也为这些基础类提供了相应的API文档,用于告诉开发者如何使用这些类,以及这些类里包含的方法

3>Java类的组织形式

4、字符类型char

字符类型可以表示单个字符,字符类型是char,char是两个字节(可以存放汉字),多个字符我们用字符串String

1>字符常量是用单引号(‘’)括起来的单个字符。例如:charv1='a'、charv2='辉'、charv3='9'

2>Java中还允许使用转义字符来将其后的字符转变为特殊字符型常量。例如:charv3=‘\n''\n'表示换行符

3>在java中,char的本质是一个整数,在输出时,是unicode码对应的字符

4>可以直接给char赋一个整数,然后输出时,会按照对应的unicode字符输出

5>char类型是可以进行运算的,相当于一个整数,因为它都对应有unicode码.

publicclasstest{publicstaticvoidmain(String[]args){charv1='a';charv2=98;charv3='a'+2;charv4='赵';charv5='\t';charv6='王';System.out.println(v1+""+v2+""+v3);//abcSystem.out.println(v1+v2+v3);//294System.out.println((int)v1);//97System.out.println(v4);//赵System.out.println(v5);//换行符System.out.println(v4+v6);//65792v4和v6本质上是整数,所以结果为将他的码值加起来}}字符型存储到计算机中,需要将字符对应的码值(整数)找出来,比如'a'

存储:'a'==>码值97==>二进制(1100001)==>存储

读取:二进制(1100001)==>97==>'a'==>显示

5、字符编码表

ASCII:ASCIl编码表一个字节表示,一个128个字符,实际上一个字节可以表示256个字符,只用了128个

Unicode:Unicode编码表固定大小的编码使用两个字节来表示字符,字母和汉字统一都是占用两个字节,这样浪费空间

utf-8:大小可变的编码表,字母使用1个字节,汉字使用3个字节

gbk:可以表示汉字,而且范围广,字母使用1个字节,汉字2个字节

gb2312:可以表示汉字,gb2312

big5码:繁体中文、台湾、香港

ASCII码介绍

上个世纪60年代,美国制定了一套字符编码(使用一个字节),对英语字符与二进制位之间的关系,做了统一的规定。这被称为ASCII码

ASCII码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位统一规定为0

特别提示:一个字节可以表示256个字符,ASCII码只用了128个字符.

缺点:不能表示所有字符。

Unicode编码介绍

Unicode的好处:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用Unicode没有乱码的问题

Unicode的缺点:一个英文字母和一个汉字都占用2个字节,这对于存储空间来说是浪费

2的16次方是65536,所以汉字最多编码是65536个字符

编码0-127的字符是与ASCII的编码一样.比如'a'在ASCII码是0x61,在unicode码是ox0061,都对应97.因此Unicode码兼容ASCII码.

UTF-8编码介绍

UTF-8是在互联网上使用最广的一种Unicode的实现方式(改进)

UTF-8是一种变长的编码方式。它可以使用1-6个字节表示一个符号,根据不同的符号而变化字节长度

使用大小可变的编码字母占1个字节,汉字占3个字节

6、布尔类型

布尔类型也叫boolean类型,在java中booolean类型数据只允许取值true和false,无null,同时不能使用其他字符代替true或false

boolean类型占1个字节,boolean类型适于逻辑运算,一般用于程序流程控制

publicclasstest{publicstaticvoidmain(String[]args){booleanvar=true;if(var==true){System.out.println("ThisisTrue.");}else{System.out.println("ThisisFalse");}}}7、基本数据类型转换

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

数据类型按精度(容量)大小排序为

inta='a';double=80;1>有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算

2>当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据类型时,就会报错,反之就会进行自动类型转换

3>(byte,short)和char之间不会相互自动转换

4>byte,short,char他们三者可以计算,在计算时首先转换为int类型

5>boolean不参与转换

6>自动提升原则:表达式结果的类型自动提升为操作数中最大的类型

//代码示例1publicclasstype_change{publicstaticvoidmain(String[]args){bytea=10;intb=580;doublec=1314.20;doubleres=a+b+c;System.out.println(res);}}//代码示例2publicclasstype_change{publicstaticvoidmain(String[]args){doublec=1314;System.out.println(c);}}//代码示例3publicclasstype_change{publicstaticvoidmain(String[]args){bytea=13;shortb=200;charc='a';intres=a+b+c;System.out.println(res);}}8、强制类型转换

自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(),但可能造成精度降低或溢出。

publicclasstype_change{publicstaticvoidmain(String[]args){inta=9527;byteres=(byte)a;System.out.println(res);}}上图的res结果为55,int类型的9527转为二进制为:00000000000000000010010100110111,因为byte为一个字节,所以只会保留上述二进制中的最后8位,即00110111=55,这种现象称为精度降低

强制类型转换细节说明

1>当进行转换的数据精度从大——>小,就需要使用到强制转换

2>强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级

3>char类型可以保存int的常量值,但不能保存int的变量值(byte同理),需要强转,因为变量的大小之前是固定好了的

4>byte和short、char类型在进行运算时,当做int类型处理

5>bytea=100;在给变量a赋值的时候,首先会判断100在不在byte的范围内,如果在的话则就赋值,不在则报错。

#案例演示1publicclasstype_change{publicstaticvoidmain(String[]args){intres=(int)10*3.5;//会报错intres=(int)(10*3.5);System.out.println(res);}}//案例演示2publicclasstype_change{publicstaticvoidmain(String[]args){inta=97;charb=97;//char可以保存int的常量值charres=(char)a;//如果保存int的变量值则需要强转System.out.println(res);//打印的是97对应的字母}}//案例演示3publicclasstype_change{publicstaticvoidmain(String[]args){bytea=97;shortb=97;charc=97;intres=a+b+c;System.out.println(res);//结果:291}}基本数据类型和String类型的转换

在程序开发中,我们经常需要将基本数据类型转成String类型。或者将String类型转成基本数据类型。

基本类型转String类型语法:将基本类型的值+""即可

publicclassHelloWorld{publicstaticvoidmain(String[]args){inta=9527;Stringstr=a+"";System.out.println(str);//9527System.out.println(str+1);//95271}}String类型转基本数据类型

语法:通过基本类型的包装类调用parseXX方法即可

publicclassHelloWorld{publicstaticvoidmain(String[]args){Stringstr="88";inta=Integer.parseInt(str);byteb=Byte.parseByte(str);shortc=Short.parseShort(str);longd=Long.parseLong(str);floate=Float.parseFloat(str);doublef=Double.parseDouble(str);booleang=Boolean.parseBoolean("true");System.out.println(a+1);System.out.println(b+1);System.out.println(c+1);System.out.println(d+1);System.out.println(e);System.out.println(f);System.out.println(g);}}注意事项

在将String类型转成基本数据类型时,要确保String类型能够转成有效的数据,比如我们可以把“123",转成一个整数,但是不能把"hello”转成一个整数,如果格式不正确,就会抛出异常,程序就会终止。

publicclasstest{publicstaticvoidmain(String[]args){Stringname="赵大大";shortage=22;floatgrade=99.99F;chargender='男';Stringhobby="女";System.out.println("姓名\t年龄\t成绩\t性别\t爱好\n"+name+"\t"+age+"\t"+grade+"\t"+gender+"\t"+hobby);}}五、运算符

运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。

算术运算符、赋值运算符、关系运算符[比较运算符]、逻辑运算符、位运算符(需要二进制基础)、三元运算符

1、算术运算符

算术运算符是对数值类型的变量进行运算的,在Java程序中使用的非常多。

2>当对一个数取模时,可以等价a%b=a-a/b*b,这样我们可以看到取模的一个本质运算。(a/b是java中的除法特点)

3>当自增作为一个独立语言使用时,不管是++i、还是i++都是一样的,等价于i=i+1

4>当自增作为一个表达式使用时:j=++i等价i=i+1、j=i

5>当自增作为一个表达式使用时:j=i++等价j=i、i=i+1

算术运算符练习题

publicclassrun{publicstaticvoidmain(String[]args){inti=1;i=i++;//规则使用临时变量:(1)temp=i、(2)i=i+1、(3)i=tempSystem.out.println(i);//打印结果:1intk=1;k=++k;//规则使用临时变量:(1)k=k+1、(2)temp=k、(3)k=tempSystem.out.println(k);//打印结果:2}}//定义一个变量保存华氏温度,华氏温度转换摄氏温度的公式为:5/9*(华氏温度-100),请求出华氏温度对应的摄氏温度。[234.5]publicclasstest{publicstaticvoidmain(String[]args){doublehuashi=234.5;doublesheshi=5.0/9*(huashi-100);//注意这里必须是5.0,不然在java里5/9=0的System.out.println(sheshi);}}(int)(Math.random()*100)+1;//生成1个1-100的随机数Math.random()方法可以生成[0,1)之间的数字,如果用这个数字乘以3就是一个从[0,3)之间的数字2、关系运算符

关系运算符也叫比较运算符,关系运算符的结果都是boolean型,也就是要么是true,要么是false

关系表达式经常用在if结构的条件中或循环结构的条件中

publicclassHelloWorld{publicstaticvoidmain(String[]args){intnumber_first=10;intnumber_second=20;System.out.println(number_first==number_second);//falseSystem.out.println(number_first!=number_second);//trueSystem.out.println(number_firstnumber_second);//falseSystem.out.println(number_first<=number_second);//trueSystem.out.println(number_first>=number_second);//falsebooleanflog=number_first!=number_second;//可以将关系表达式的结果赋给布尔类型的变量System.out.println(flog);//true}}1>关系运算符的结果都是boolean型,也就是要么是true,要么是false

2>关系运算符组成的表达式,我们称为关系表达式:a>b

3>比较运算符"=="不能误写成"=","=="为等于。"="为赋值

3、逻辑运算符

用于连接多个条件(多个关系表达式),最终的结果也是一个boolean值。

逻辑运算符一览

短路与:&&

短路或:||

逻辑与:&

逻辑或:|

取反:!

逻辑异或:^

a&b:&叫逻辑与,当a和b同时为true,则结果为true,否则为false

a&&b:&&叫短路与,当a和b同时为true,则结果为true,否则为false

alb:|叫逻辑或,当a和b,有一个为true,则结果为true,否则为false

a||b:叫短路或,当a和b,有一个为true,则结果为true,否则为false

!a:叫取反,或者非运算。当a为true,则结果为false;当a为false,结果为true

a^b:叫逻辑异或,当a和b不同时,则结果为true,否则为false

publicclasstest{publicstaticvoidmain(String[]args){intnumber_first=10;intnumber_second=20;System.out.println(!(number_first9)^(10>8));//true}}&&和&使用区别

&&短路与:如果第一个条件为false,则第二个条件不会执行判断,最终结果就是false,效率高

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

开发中,我们基本使用&&

publicclasstest{publicstaticvoidmain(String[]args){intnumber_first=10;intnumber_second=20;if(number_first<5&&++number_second>15){System.out.println("条件为真");}System.out.println("number_first="+number_first+"number_second="+number_second);//number_first=10number_second=20}}如上图,因为number_first<5为假,所以++number_second就不会执行,如果为逻辑与&的话,就会执行++number_second了

|和||使用区别

||短路或:如果第一个条件为true,则第二个条件不会执行判断,最终结果就为true,效率高

|逻辑或:不管第一个条件是否为true,第二个条件都要判断,效率低

开发中,我们基本使用||

publicclasstest{publicstaticvoidmain(String[]args){intnumber_first=10;intnumber_second=20;if(number_first<15||++number_second>30){System.out.println("条件为真");}System.out.println("number_first="+number_first+"number_second="+number_second);//number_first=10number_second=20}}如上图,因为number_first<15为真,所以++number_second就不会执行,如果为逻辑或|的话,就会执行++number_second了

逻辑运算符练习题

注意:x++==6,因为是后++,所以是先判断x==6,再进行自增,x++==6是一个表达式

所以答案如下:6,6|6,5|11,6|11,5

注意:(y=true)是一个赋值语句,&&判断的是赋值完之后的y的值

所以答案为50

4、赋值运算符

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

基本赋值运算符:inta=10

复合赋值运算符:+=、-=、*=、/=、%=

a+=b:[等价a=a+b;]

a-=b:[等价a=a-b;]

1>运算顺序从右往左intnum=a+b+c;,先计算a+b+c的值再赋值给num变量

2>赋值运算符的左边只能是变量,右边可以是变量、表达式、常量值

intnum=20、intnum2=78*34-10、intnum3=a

3>复合赋值运算符等价于下面的效果

比如:a+=3:等价于a=a+3其他类推

4>复合赋值运算符会自动进行类型的强制转换

5、三元运算符

基本语法

条件表达式?表达式1:表达式2;运算规则

1、如果条件表达式为true,运算后的结果是表达式1

2、如果条件表达式为false,运算后的结果是表达式2

使用细节

1、表达式1和表达式2要为可以赋给接收变量的类型(或可以自动转换)

2、三元运算符可以转成ifelse语句

publicclasstest{publicstaticvoidmain(String[]args){intnum_first=1;intnum_second=20;intresult=num_second>num_first13.14:5.20;//会报错intresult=num_second>num_first(int)13.14:(int)5.20;//会损失精度doubleresult=num_second>num_first13.14:5.20;//niceSystem.out.println(result);}}6、运算符优先级

运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序

如下表,上一行运算符总优先于下一行。只有单目运算符、赋值运算符是从右向左运算的

7、标识符规则与规范

标识符概念:Java对各种变量、方法和类等命名时使用的字符序列称为标识符

凡是自己可以起名字的地方都叫标识符intnumber_first=90;中的num_first就是标识符

标识符的命名规则(必须遵守)

1.由26个英文字母大小写、0-9、_或$组成

2、数字不可以开头(int3ab=1;是错误)

3、不可以使用关键字和保留字,但能包含关键字和保留字

4、Java中严格区分大小写,长度无限制。intabc与intAbc是两个变量

5、标识符不能包含空格。(intab=90;是错误的)

标识符的命名规范(更加专业)

1、包名:多单词组成时所有字母都小写:aaa.bbb.ccc比如com.zrh.crm

2、类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz【大驼峰】比如:TankShotGame

3、变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZz【小驼峰,简称驼峰法】比如:tankShotGame

4、常量名:所有字母都大写,多单词时每个单词用下划线连接:XXX_YYY_ZZZ比如:定义一个所得税率TAX_RATE

8、关键字与保留字

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

Java保留字:现有Java版本尚未使用,但以后版本可能会作为关键字使用

自己命名标识符时要避免使用这些保留字byValue、cast、future、generic、inner、operator、outer、rest、var、goto、const

六、键盘输入

七、进制

对于整数,有四种表示方式:

二进制:0,1,满2进1,以0b或0B开头

十进制:0-9,满10进1

八进制:0-7,满8进1,以数字0开头表示。

十六进制:0-9及A(10)-F(15),满16进1,以0x或0X开头表示,此处的AF不区分大小写。

1、进制转换

二进制转十进制规则:从最低位(右边)开始,将每个位上的数提取出来,乘以2的(位数-1)次方,然后求和

0b1011=1*2^0+1*2^1+0*2^2+1*2^3=11

八进制转十进制:从最低位(右边)开始,将每个位上的数提取出来,乘以8的(位数-1)次方,然后求和

0234=4*8^0+3*8^1+2*8^2=156

十六进制转十进制规则:从最低位(右边)开始,将每个位上的数提取出来,乘以16的(位数-1)次方,然后求和

0X23A=10*16^0+3*16^1+2*16^2=570

十进制转二进制规则:将该数不断除以2,直到商为0为止,然后将每步得到的余数倒过来,就是对应的二进制

158=158/2=79……0、79/2=39……1、39/2=19……1、19/2=9……1、9/2=4……1、4/2=2……0、2/2=1……0;所以158=ob10011110

十进制转八进制规则:将该数不断除以8,直到商为0为止,然后将每步得到的余数倒过来,就是对应的八进制

131=131/8=16……3、16/8=2……0;所以131=0203

十进制转十六进制规则:将该数不断除以16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的十六进制

237=237/16=14……13;所以237=0XED

二进制转八进制规则:从低位开始,将二进制数每三位一组,转成对应的八进制数即可

0b11010110=011、010、110=3、2、6=0326

二进制转十六进制规则:从低位开始,将二进制数每四位一组,转成对应的十六进制数即可

0b11010110=1101、0110=13、6=0XD6

八进制转二进制规则:将八进制数每1位,转成对应的一个3位的二进制数即可

0237=2、3、7=010、011、111=ob10011111

十六进制转二进制规则:将十六进制数每1位,转成对应的4位的一个二进制数即可

0X23B=2、3、B=0010、0011、1011=ob1000111011

2、原码反码补码

对于有符号的而言:

1>二进制的最高位是符号位:0表示正数、1表示负数

2>正数的原码,反码,补码都一样(三码合一)

3>负数的反码=它的原码符号位不变,其它位取反(0变1、1变0)

4>负数的补码=它的反码+1,负数的反码=负数的补码-1

5>0的反码,补码都是0

6>java没有无符号数,换言之,java中的数都是有符号的

7>在计算机运算的时候,都是以补码的方式来运算的

8>当我们看运算结果的时候,要看他的原码

#例如:int2int2的源码=00000000000000000000000000000010因为2是正数,所以2的原码、补码、反码都一样,三码合一#例如:int-2int-2的源码=10000000000000000000000000000010int-2的反码=11111111111111111111111111111101int-2的补码=111111111111111111111111111111103、位运算符

java中有7个位运算:&、|、^、~、>>、<<、>>>

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

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

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

按位取反~:0变1,1变0

算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位

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

逻辑右移>>>:也叫无符号右移,低位溢出,高位补0

八、程序流程控制

在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句:顺序控制、分支控制、循环控制

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

1、分支控制

让程序有选择的的执行,分支控制有三种

//1、单分支ifpublicclassHelloWorld{publicstaticvoidmain(String[]args){intage=20;if(age>18){System.out.println("你的年龄大于18,请为自己的行为负责!");}}}//2、双分支if-elsepublicclasstest{publicstaticvoidmain(String[]args){intyearNum=2020;if((yearNum%4==0&&yearNum%100!=0)||yearNum%400==0){System.out.print("此年份是闰年");}else{System.out.print("此年份不是闰年");}}}//3、多分支if-elseif-...-elsepublicclasstest{publicstaticvoidmain(String[]args){intgrade=95;if(grade>=100){System.out.print("信用极好");}elseif(80多分支可以没有else,如果所有的条件表达式都不成立,则一个执行入口都没有

2>如果有else,如果所有的条件表达式都不成立,则默认执行else代码块

2、嵌套分支

在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支,建议不要超过3层,可读性不好

publicclasstest{publicstaticvoidmain(String[]args){doublescore=9.5;if(score>8.0){chargender='女';//myScanner.next().charAt(0)本质是将字符串的第一个字符转成charif(gender=='男'){System.out.print("恭喜你进入男子组决赛");}elseif(gender=='女'){System.out.print("恭喜你进入女子组决赛");}else{System.out.print("性别错误,无法参加决赛");}}else{System.out.println("Sorry,你已被淘汰");}}}3、switch分支结构

2>表达式对应一个值

3>case常量1:当表达式的值等于常量1,就执行语句块1

4>break表示退出swtich

5>如果和case常量1匹配,就执行语句块1,如果没有匹配,就继续匹配case常量2

6>如果一个都没有匹配上,执行default

switch结构细节

1>表达式数据类型,应和case后的常量类型一致,或者是可以自动转成可以相互比较的类型,比如输入的是字符,常量是int就可以,因为char可以自动转为int

2>switch中的表达式返回值必须是:(byte、short、int、char、enum[枚举]、String)

publicclasstest{publicstaticvoidmain(String[]args){doublec=1.1;switch(c){//错误,后面类型不符合规定case1.1://错误,后面类型不符合规定System.out.println("ok3");break;}}}3>case子句中的值必须是常量或常量表达式,而不能是变量

4>default子句是可选的,当没有匹配的case时,执行default

5>break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有写break,程序会顺序执行到switch结尾,除非遇到break;

//根据用于指定月份,打印该月份所属的季节//3.4.5春季、6.7.8夏季、9.10.11秋季、12.1.2冬季//[必须使用Switch且必须使用穿透]publicclasstest{publicstaticvoidmain(String[]args){intc=8;switch(c){case3:case4:case5:System.out.print("春季");break;case6:case7:case8:System.out.print("夏季");break;case9:case10:case11:System.out.print("秋季");break;case12:case1:case2:System.out.print("冬季");break;default:System.out.print("输入月份有误");}}}switch和if的选择

1>如果判断的具体数值不多,而且符合byte、short、int、char、enum[枚举]、String这6种类型。虽然两个语句都可以使用,建议使用swtich语句

2>其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广

4、循环控制-for循环

1>for关键字,表示循环控制

2>for有四要素①循环变量初始化②循环条件③循环操作④循环变量迭代

3>循环操作,这里可以有多条语句,也就是我们要循环执行的代码

4>如果循环操作(语句)只有一条语句,可以省略{},建议不要省略

for循环细节

1>循环条件是返回一个布尔值的表达式

2>for(;循环判断条件;)中的循环变量初始化和变量迭代可以写到其它地方,但是两边的分号不能省略

#循环变量初始化如果写到for外面,那么之后还可以使用循环变量的值,如果循环变量写到for循环里,那么就只能在for循环里面使用publicclasstest{publicstaticvoidmain(String[]args){inti=1;//循环变量初始化写到外面for(;i<10;){System.out.println("Hello,World"+i);i++;}System.out.print(i);//for循环外还可以调用i变量}}循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代语句,中间用逗号隔开

publicclasstest{publicstaticvoidmain(String[]args){for(inti=1,j=0;i<10;i+=2,j++){System.out.println("i="+i+"j="+j);}}}for循环练习

//打印1~100之间所有是9的倍数的整数,统计个数及总和.publicclasstest{publicstaticvoidmain(String[]args){System.out.println("符合条件的整数如下:");inti=1;intcount=0;intsum=0;for(;i<=100;i++){if(i%9==0){count++;sum+=i;System.out.print(i+"\t");}}System.out.print("\n统计个数为:"+count+"\n总和为:"+sum);}}for(;;;){}//表示无限循环,也叫死循环,可以配合break一起使用5、循环控制-while循环

while循环也有四要素,只不过四要素的位置与for循环不一样而已

细节说明

2>while循环是先判断再执行语句

publicclasstest{publicstaticvoidmain(String[]args){//打印1-100之间所有能被3整除的数,使用whileintnumber=1;while(number<=100){switch(number%3){case0:System.out.print(number+"\t");}number++;}}}6、do…while循环

1>dowhile是关键字

2>也有循环四要素,只是位置不一样

3>先执行,再判断,也就是说,一定会至少执行一次

4>最后有一个分号

2>do...while循环是先执行,再判断,因此至少执行一次

7、多重循环

多重循环也叫嵌套循环,将一个循环放在另一个循环体内,就形成了嵌套循环。其中for、while、do..while均可以作为外层循环和内层循环。【建议一般使用两层,最多不要超过3层,否则,代码的可读性很差】

实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环

设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次

8、化繁为简、先死后活

统计3个班成绩情况,每个班有5名同学,求出各个班的平均分和所有班级的平均分,并统计三个班及格人数(学生的成绩从键盘输入)

1>化繁为简

①要统计三个班的成绩情况,可以先统计一个班的成绩情况,因为每个班有5个学生,每个学生的成绩都是键盘输入,所以可以设置for循环输入5次

②成绩输入完后计算平均分,可以定义一个doublesum把5名学生的成绩进行累和,然后除以人数就可以得到一个班平均值

③一个班处理完了,可以处理三个班,一个班的代码框架完成后,可以在代码框架外加一个循环3次的for循环,这样就可以得到3个班的成绩情况

④要计算三个班的平均分,可以定义一个变量doubletotalScore来累和每个班成绩,然后除以三个班的人数就是三个班的平均值

⑤统计三个班的及格人数,可以设置一个变量intcount,如果输入学生的成绩>=60,那么就对count++,最后打印count即可

2>先死后活

①上面所说每班5个学生,就做了5次的for循环,可以将5设置成变量

②上面所说3个班级,就做了3次的for循环,可以将3设置成变量

先死后活的含义就是先将内容写死,然后通过变量将内容替换,这样就可以修改变量的内容达到灵活的目的

9、跳转控制语句break

break语句用于终止某个语句块的执行,一般使用在switch或者循环[for、while、do-while]中

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

1>break语句可以指定退出哪层

2>label1是标签,名字由程序员指定

3>break后指定到哪个label就退出到哪里

4>在实际的开发中,尽量不要使用标签.

5>如果没有指定break,默认退出最近的循环体

上图代码将breaklabel1取消注释以后,结果如下:

注意:判断两个字符安川是否相等需要用到String下的equals方法

"丁真".equals(username)10、跳转控制语句continue

1>continue语句用于结束本次循环,继续执行下一次循环

2>contimue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环﹐这个和前面的标签的使用的规则一样

publicclasstest{publicstaticvoidmain(String[]args){label1:for(inti=1;i<=3;i++){label2:for(intk=1;k<=3;k++){if(k==2){continue;//等价于continuelabel2;结果为打印三次k=1、k=2//continuelabel1;结果为打印三次k=1}System.out.println("k="+k);}}}}11、跳转控制语句return

return使用在方法上,表示跳出所在的方法,在讲解方法的时候,会详细的介绍,这里我们简单的提一下

注意:如果return写在main方法,表示退出程序

publicclasstest{publicstaticvoidmain(String[]args){inti=1;do{if(i==2){return;}System.out.println("i="+i);i++;}while(i<=3);System.out.println("循环结束");//return之后这句话就不会被执行}}12、程序控制结构作业

//计算1-1/2+1/3-1/4......1/100的和publicclasstest{publicstaticvoidmain(String[]args){doublesum=0.0;for(inti=1;i<=100;i++){if(i%2==0){sum-=(1.0/i);//注意1.0,注意java中/的陷阱}else{sum+=(1.0/i);}}System.out.println("和="+sum);}}//求1+(1+2)+(1+2+3)+(1+2+3+4)+...+(1+2+...+100)的结果//第一种publicclasstest{publicstaticvoidmain(String[]args){intsum=0;intres=0;for(inti=1;i<=100;i++){sum+=i;res+=sum;}System.out.println("result="+res);}}//第二种publicclasstest{publicstaticvoidmain(String[]args){intsum=0;for(inti=1;i<=100;i++){for(intk=1;k<=i;k++){sum+=k;}}System.out.println("result="+res);}}九、数组

数组可以存放多个同一类型的数据,数组也是一种数据类型,是引用类型,即:数组就是一组数据

publicclasstest{publicstaticvoidmain(String[]args){intarr[]=newint[5];//int表示数组为int类型//arr表示数组的名称//[]表示数据//newint[5]表示在内存中创建数组,数组可以存放5个元素System.out.print(arr.length);//arr.length表示arr数组的长度arr[0]=520;//给数组的第一个元素赋值,数组的索引是从0开始的System.out.print(arr[0]);}}1、数组的使用方式

使用情况:知道数组有多少元素且知道元素具体的值

publicclasstest{publicstaticvoidmain(String[]args){//int[]arr;也可以intarr[]={1,2,3};//以上一句代码相当于//intarr[]=newint[3];//arr[0]=1;//arr[1]=2;//arr[2]=3;}}注意:Stringstrs[]=newString[]{"a","b","c"};//这样是正确的Stringstrs[]=newString[3]{"a","b","c"};//这样是错误的2、数组使用注意事项和细节

1>数组是多个相同类型数据的组合(自动类型转换的也可以放在同一个数组里),实现对这些数据的统一管理

2>数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用

3>数组创建后,如果没有赋值,有默认值

int0、short0、byte0、long0、float0.0、double0.0、char/u0000、booleanfalse、Stringnull

5>数组的下标是从0开始的

6>数组下标必须在指定范围内使用,否则报:下标越界异常,比如

7>数组属引用类型,数组型数据是对象(object)

//创建一个char类型的26个元素的数组,分别放置'A‘-'Z',使用for循环访问所有元素并打印出来publicclasstest{publicstaticvoidmain(String[]args){chararray[]=newchar[26];for(inti=0;i<=25;i++){array[i]=(char)('A'+i);//array[]是数组类型,array[1]是char类型System.out.print(array[i]+"");}}}3、赋值机制与数组拷贝

在引用传递的赋值机制下,修改array_second元素的值是会影响到array_first元素的值的,因为array_firs和array_second指向的是同一个内存地址

如果想要拷贝一个相互不影响的数组,那么就需要用拷贝的赋值机制对数组进行拷贝,操作如下:

新建一个数组,数组的长度与需要拷贝的数组相同,再将需要拷贝的数组元素的值一一赋给新建数组的元素的值即可

publicclasstest{publicstaticvoidmain(String[]args){intarray_first[]={1,3,5,7,9};intarray_second[]=newint[array_first.length];for(inti=0;i

要求:把数组的元素内容反转

//根据规律反转publicclassTest{publicstaticvoidmain(String[]args){intarrary_first[]={1,2,3,4,5,6};inttemp=0;for(inti=0;i=0;i--){arrary_second[arrary_first.length-i-1]=arrary_first[i];}arrary_first=arrary_second;for(inti=0;i

//实现动态的给数组添加元素效果,实现对数组扩容//用户可以通过如下方法来决定是否继续添加:添加成功,是否继续y/nimportjava.util.Scanner;publicclasstest{publicstaticvoidmain(String[]args){intarray[]={1,2,3};ScannermyScanner=newScanner(System.in);System.out.println("原始数组内容如下:");for(inti=0;i

7、排序

排序是将多个数据,依指定的顺序进行排列的过程

排序的分类:

内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法)

外部排序法:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)

冒泡排序法

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

将五个无序:24,69,80,57,13使用冒泡排序法将其排成一个从小到大的有序数列

publicclasstest{publicstaticvoidmain(String[]args){intarray[]={24,69,80,57,13};inttemp=0;inttime=0;for(intk=1;karray[i+1]){temp=array[i];array[i]=array[i+1];array[i+1]=temp;time++;//插个眼}}if(time==0)break;//眼==0,就代表顺序已经排好了}for(inti=0;i

1>从定义形式上看:int[][]name或者intname[][]

2>二维数组的每一个元素是一个一维数组

二维数组的每个元素是一维数组,所以如果需要得到每个一维数组的值还需要再次遍历

访问第(i+1)个一维数组的第j+1个值:arr[i][j];

arr[i]表示二维数组的第i+1个元素比如:arr[0]表示二维数组的第一个元素

arr.length表示二维数组的长度、arr[i].length得到对应的每个一维数组的长度

1、二维数组在内存中的存在形式

2、二维数组的使用方式

创建二维数组,二维数组中有3个一维数组,但是每个一维数组还没有开辟数据空间

publicclasstest{publicstaticvoidmain(String[]args){intarray[][]=newint[3][];//没有创建一维数组元素的个数for(inti=0;i静态初始化

publicclasstest{publicstaticvoidmain(String[]args){intarray[][]=new{{1,2,3},{1,2},{1}};//定义了一个二维数组//二维数组有三个元素,每个元素都是一维数组//第一个一维数组有3个元素、第二个有2个元素、最后一个有一个元素}}3、二维数组使用细节和注意事项

3>二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同

比如:map[][]是一个二维数组

intmap[][]={{1,2},{3,4,5}}

map[0]是一个含有两个元素的一维数组,map[1]是一个含有三个元素的一维数组构成,我们也称为列数不等的二维数组

int[]x,y[]//表示x是int类型一维数组,y是int类型的二维数组4、二维数组练习

//已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序//比如:[10,12,45,90],添加23后,数组为[10,12,23,45,90]importjava.util.Scanner;publicclasstest{publicstaticvoidmain(String[]args){ScannermyScanner=newScanner(System.in);System.out.print("请输入插入的数:");intval=myScanner.nextInt();inttemp=0;intarray[]={10,12,45,90,99,102,129,168};intarray_temp[]=newint[array.length+1];for(inti=0;ival){temp++;//i+1的目的是为了将array_temp的i空出来给valarray_temp[i+1]=array[i];if(temp==1){//temp等于1的时候对应的i就是val的索引array_temp[i]=val;}}}//防止val的值比array每一个元素的值都大if(array_temp[array.length]==0){array_temp[array.length]=val;}array=array_temp;for(inti=0;i

1、类与对象

类是抽象的,概念的,代表一类事物,比如人类、猫类、狗类......

类是数据类型;对象是具体的、实际的,代表一个具体事物,即是实例

类是对象的模板,对象是类的一个个体,对应一个实例

publicclasstest{publicstaticvoidmain(String[]args){Cathk=newCat();//创建一个对象hk.name="flower";hk.age=2;hk.color="white";Catxk=hk;System.out.print("这只猫的信息为:"+hk.name+""+hk.age+""+hk.color);}}classCat{//定义Cat类Stringname;intage;Stringcolor;}2、对象在内存中的存在形式

非基本数据类型都存放在方法区的常量池中,基本数据类型就直接保存在类所在的内存地址里

类和对象的内存分配机制,Java内存的结构分析

1>栈:一般存放基本数据类型(局部变量)

2>堆:存放对象(Cathk,数组等)

3>方法区:常量池(常量,比如字符串),类加载信息

注意:如果xk=null;这代表xk置空,置空之后xk与创建的对象就失去了链接

3、属性

从概念或叫法上看:成员变量=属性=field(字段)(即成员变量是用来表示属性的,本文中统一叫属性)

classCat{//定义Cat类Stringname;//成员变量、属性、字段intage;Stringcolor;String[]hosts;//属性可以是基本数据类型,也可以是引用类型(对象,数组)}注意事项和细节说明

1>属性的定义语法同变量,示例:访问修饰符属性类型属性名;

简单的介绍访问修饰符:控制属性的访问范围

有四种访问修饰符public、proctected、默认、private

2>属性的定义类型可以为任意类型,包含基本类型或引用类型

3>属性如果不赋值,有默认值,规则和数组一致

具体说:int0、short0、byte0、long0、float0.0、double0.0、char/u0000、booleanfalse、Stringnull

publicclasstest{publicstaticvoidmain(String[]args){Cathk=newCat();//hk是对象名,也叫对象引用//newCat()为创建的对象空间,是真正的对象,对象名只是指向了这个对象空间而已}}创建对象及访问属性

1>先加载Cat类信息(属性和方法信息,只会加载一次)

2>在堆中分配空间,进行默认初始化(int0、double0.0.....)

3>把地址赋给hk,hk就指向对象

4>进行指定初始化,比如hk.name="flower"hk.age=2

4、方法

1>方法写好后,如果不去调用(使用),不会输出

2>先创建对象,然后调用方法即可

publicclasstest{publicstaticvoidmain(String[]args){Personhk=newPerson();//创建一个对象hk.speak();//调用speak方法}}classPerson{//定义Cat类Stringname;intage;//1、public表示方法公开//2、void表示方法没有返回值//3、speak()中speak为方法名,()为形参列表//4、{}方法体,可以写我们要执行的代码体publicvoidspeak(){System.out.print("Thisisagoodman.");}}方法快速入门

publicclasstest{publicstaticvoidmain(String[]args){Personhk=newPerson();//创建一个对象hk.cal(500);//调用cal方法,同时传入参数,即n=500intresult=hk.getSum(10,20);System.out.println(result);}}classPerson{//定义Cat类Stringname;intage;//定义speak方法publicvoidspeak(){System.out.println("Thisisagoodman.");}//定义cal方法publicvoidcal(intn){//表示当前有一个形参n(形式参数),可以接受用户输入intsum=0;for(inti=1;i<=n;i++){sum+=i;}System.out.println("1+2+...+"+n+"="+sum);}//定义getSum方法//1、piblic后的int表示方法执行后,返回一个int值//2、(intnum1,intnum2)表示形参列表,可以接受用户传入两个参数//3、return表示将结果返回publicintgetSum(intnum1,intnum2){intres=num1+num2;returnres;}}方法的调用机制

这里使用getSum方法进行演示

方法调用总结

1>当程序执行到方法时,就会开辟一个独立的空间(栈空间)

2>当方法执行完毕,或者执行到return语句时,就会返回相应的结果到调用方法的地方

3>返回后,栈空间被垃圾回收机制回收,然后继续执行方法后面的代码

4>当main方法(栈)执行完毕,整个程序退出

5、成员方法的定义及细节

1>形参列表:表示成员方法输入的参数cal(intn)、getSum(intnum1,intnum2)

2>返回数据类型:表示成员方法输出,void表示没有返回值

3>方法主体:表示为了实现某一功能代码块

4>return语句不是必须的

成员方法的好处:提高代码的复用性、可以将实现的细节封装起来,然后供其他用户来调用即可

方法细节及注意事项

返回数据类型

1>一个方法最多有一个返回值,如果需要返回多个值可以返回数组

2>返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)

publicclasstest{publicstaticvoidmain(String[]args){myToolstools=newmyTools();//创建对象int[]result=tools.printArr(20,10);System.out.println("result[0]="+result[0]);System.out.println("result[1]="+result[1]);}}classmyTools{publicint[]printArr(intnum1,intnum2){//返回数据类型为数组int[]res=newint[2];//创建数组res[0]=num1+num2;res[1]=num1-num2;returnres;//返回数组}}3>如果方法要求有返回数据类型,则方法体中最后的执行语句必须为return值,而且要求返回值类型必须和return的值类型一致或兼容

4>如果方法是void,则方法体中可以没有retun语句,或者只写return;(即return后没有返回值)

方法名

遵循驼峰命名法,最好见名知义,表达出该功能的意思即可,比如得到两个数的和getSum,开发中按照规范

形参列表

1>一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开,比如:getSum(intn1,intn2)

2>参数类型可以为任意类型,包含基本类型或引用类型,比如:printArr(int[][]map)

3>调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数

4>方法定义时的参数称为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参,实参和形参的类型要一致或兼容、个数、顺序必须一致

方法体

方法体里面写完成功能的具体的语句

可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能再定义方法!

即:方法不能嵌套定义,(只是不能嵌套定义,但是方法体里可以调用其他方法)

6、方法调用细节说明

1>同一个类中的方法调用:直接调用即可

案例演示:myTools类中的sayOk方法调用printArr方法

publicclasstest{publicstaticvoidmain(String[]args){myToolstools=newmyTools();//创建对象tools.sayOk(520);}}classmyTools{//定义printArr方法publicvoidprintArr(intnum){//无数据类型System.out.println("你输入的数字为="+num);}//定义sayOk方法publicvoidsayOk(intnum){System.out.println("sayOk方法已调用");printArr(num);//调用同一个类的printArr方法}}2>跨类中的方法A类调用B类方法:需要通过对象名调用,比如:对象名.方法名(参数);

案例演示:myTools类的sayHello方法调用herTools类的printArr方法

7、成员方法传参机制

1>基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools();intn=10;intm=20;tools.swap(n,m);System.out.print("main方法的:n="+n+"m="+m);//main方法的:n=10m=20}}classMytools{publicvoidswap(intn,intm){inttemp=n;n=m;m=temp;System.out.println("swap方法的:n="+n+"m="+m);//swap方法的:n=20m=10}}2>引用类型传递的是地址(传递也是值,但值是地址),可以通过形参的改变影响实参

8、克隆对象

编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象,即克隆对象

注意:要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同

publicclasstest{publicstaticvoidmain(String[]args){Personp=newPerson();p.name="King";p.age=22;Mytoolstools=newMytools();Personp2=tools.copyPerson(p);System.out.println("P的属性为:"+"p.name="+p.name+"p.age="+p.age);System.out.println("P2的属性为:"+"p2.name="+p2.name+"p2.age="+p2.age);System.out.println(p==p2);//判断p与p2是否属于同一对象空间}}classPerson{Stringname;intage;}classMytools{//编写方法的思路//1、方法的返回类型Person,属于一个类(int是100的类)//2、方法的名字copyPerson//3、方法的形参是一个对象,对象又是Person类的实例,所以为PersonppublicPersoncopyPerson(Personp){Personp2=newPerson();p2.name=p.name;p2.age=p.age;returnp2;}}十二、递归

递归就是方法自己调用自己,每次调用时传入不同的变量

递归细节

1、执行一个方法时,就创建一个新的受保护的独立空间(栈空间)

2、方法的局部变量是独立的,不会相互影响,比如上图中的number变量

3、如果方法中使用的是引用类型变量(比如数组、对象),就会共享该引用类型的数据,那么局部变量之间就会受到影响

4、递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError

5、当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕(栈空间也就被回收)

十三、方法的重载

java中允许在同一个类中,定义多个同名的方法,但要求形参列表不一致

重载的好处:1、减轻了起名的麻烦2、减轻了记名的麻烦

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools();System.out.println(tools.m(5));System.out.println(tools.m(10,50));tools.m("HK9527");}}classMytools{publicintm(intnum){returnnum*num;}publicintm(intnum1,intnum2){returnnum1*num2;}publicvoidm(Stringstr){System.out.print(str);}}注意事项和使用细节

1、方法名必须相同

2、形参列表必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)

3、返回类型无要求,及相同与否都可以

4、在调用重载方法时,优先调用传入参数与方法定义参数的类型未发生类型转换的方法

十四、可变参数

java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法,就可以通过可变参数实现

访问修饰符返回类型方法名(数据类型...形参名){}1、可变参数的实参可以为0个或任意多个

2、可变参数的实参可以为数组

3、可变参数的本质就是数组

4、可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后

5、一个形参列表中只能出现一个可变参数

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools();tools.showScore("HK9527",85,95,87,96,88);}}classMytools{publicvoidshowScore(Stringname,double...score){doublesum=0;for(inti=0;i

1、在java编程中,主要的变量就是属性(成员变量)和局部变量

2、我们说的局部变量一般是指在成员方法中定义的变量

3、java中作用域的分类

全局变量:也就是属性,作用域为整个类体

局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中

4、全局变量(属性)可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值

注意事项和细节使用

1、属性和局部变量可以重名,访问时遵循就近原则

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools();tools.var();}}classMytools{Stringname="ZRH";//属性/全局变量publicvoidvar(){Stringname="KING";//局部变量System.out.println(name)//输出结果:KING}}2、在同一个作用域中,比如在同一个成员方法中,两个局部变量不能重名

3、属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁

局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁。

4、作用域范围不同

全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)

局部变量:只能在本类对应的方法中使用

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools();tools.var();Histoolshtools=newHistools();htools.temp(tools);//其他类通过传入对象参数调用}}classMytools{Stringname="ZRH";//属性/全局变量publicvoidvar(){intage=10;//局部变量System.out.println(name);//在本类的方法中使用全局变量System.out.println(age);//只能在本类对应的方法中使用}}classHertools{publicvoidtemp(){Mytoolsvalue=newMytools();System.out.println(value.name);//其他类通过创建对象调用}}classHistools{publicvoidtemp(Mytoolstools){System.out.println(tools.name);//其他类通过传入对象参数调用}}5、修饰符不同

全局变量/属性可以加修饰符,局部变量不可以加修饰符

classMytools{publicStringname="ZRH";//这样写是正确的,属性/全局变量可以加修饰符publicvoidvar(){publicintage=10;//这样写是错误的,局部变量不可以加修饰符,会报错}}十六、构造器

构造方法又叫构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化

[修饰符]方法名(形参列表){方法体;}它有几个特点:

1>方法名和类名相同

2>没有返回值

3>在创建对象时,系统会自动的调用该类的构造器完成对象的初始化

4>参数列表和成员方法一样的规则

5>构造器的调用,由系统完成

6>构造器的修饰符可以默认,也可以是public、protected、private

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools("Zrh");System.out.println(tools.name);//打印结果:Zrh}}classMytools{Stringname;//属性/全局变量Mytools(Stringtest_name){name=test_name;}}1、注意事项和使用细节

1>一个类可以定义多个不同的构造器,即构造器重载

比如:我们可以再给Mytools类定义一个构造器,用来创建对象的时候只指定人名,不需要指定年龄

publicclasstest{publicstaticvoidmain(String[]args){Mytoolsfirst_tools=newMytools("Zrh");//只指定姓名System.out.println(first_tools.name);//打印结果:ZrhMytoolssecond_tools=newMytools("Zrh",22);//指定姓名和年龄System.out.println(second_tools.name+""+second_tools.age);//打印结果:Zrh22}}classMytools{Stringname;//属性/全局变量intage;Mytools(Stringtest_name){name=test_name;}Mytools(Stringtest_name,inttest_age){//构造器重载name=test_name;age=test_age;}}2>构造器名和类名要相同

3>构造器没有返回值

4>构造器是完成对象的初始化,并不是创建对象

5>在创建对象时,系统自动调用该类的构造方法

6>如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器),使用javap指令反编译可以查看

7>一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显式的定义一下(这点很重要)

publicclasstest{publicstaticvoidmain(String[]args){Mytoolsfirst_tools=newMytools("Zrh");//只指定姓名Mytoolssecond_tools=newMytools();//只有显示定义了无参构造器才可以继续这样使用}}classMytools{Stringname;//属性/全局变量intage;Mytools(Stringtest_name){name=test_name;}Mytools(){//无参构造器}}2、创建对象流程分析

classPerson{//类Personintage=90;Stringname;Person(Stringn,inta){//构造器name=n;//给属性赋值age=a;//}}Personp=newPerson("小倩",20);3、流程分析(面试题)

1>加载Person类信息(Person.class),只会加载一次

2>在堆中分配空间(地址)

3>完成对象初始化

①默认初始化age=0name=null

②显式初始化age=90,name=null

③构造器的初始化age=20,name=小倩

4>在对象在堆中的地址,返回给p(p是对象名,也可以理解成是对象的引用)

十七、this

java虚拟机会给每个对象分配this用来代表当前对象

1、this的注意事项和使用细节

1>this关键字可以用来访问本类的属性、方法、构造器

2>this用于区分当前类的属性和局部变量

3>访问成员方法的语法:this.方法名(参数列表)

4>访问构造器语法:this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另外一个构造器且必须放在第一条语句)

publicclasstest{publicstaticvoidmain(String[]args){Mytoolstools=newMytools();}}classMytools{Stringname;intage;Mytools(){this("Zrh",22);//访问构造器语法必须放置在第一条语句System.out.println("Mytools()构造器被调用");}Mytools(Stringname,intage){System.out.println("Mytools(Stringname,intage)构造器被调用");}}5>this不能在类定义的外部使用,只能在类定义的方法中使用

6>this简单的说,哪个对象调用,this就代表哪个对象

2、匿名对象

匿名对象就是没有名字的对象,使用一次即会销毁

publicclasstemp{intcount=9;publicvoidcount1(){count=10;}publicstaticvoidmain(String[]args){newtemp().count1();//匿名对象存在于堆中,但是只能用一次}}3、练习题

设计类的成员变量,成员方法,可以电脑猜拳,电脑每次都会随机生成0、1、2

0表示石头、1表示剪刀、2表示布,并要可以显示输赢次数

importjava.util.Scanner;classgame{publicvoidfinger(){ScannerMyscanner=newScanner(System.in);inti=0;intj=0;do{System.out.println("请输入你的猜拳:(0=石头、1=剪刀、2=布、3=退出)");intres=Myscanner.nextInt();inttemp=(int)(Math.random()*3);if(res==3)break;if(temp-1==res||res-2==temp)i++;elsej++;System.out.println("电脑随机猜拳:"+temp+"\n你胜利的次数:"+i+"\t你失败的次数:"+j);}while(true);}}十八、IDEA的使用

1、编码设置

2、文件保存内容介绍

3、自动导入所需要的类

4、配置运行快捷键

5、生成构造器

6、查看一个类的层级关系ctrl+H

7、将光标放在一个方法上,输入ctrl+B,可以定位到方法的位置

8、创建对象时自动分配变量名

importjava.util.Scanner;publicclasstest{intage;Stringname;publicstaticvoidmain(String[]args){//newScanner(System.in).var然后回车Scannerscanner=newScanner(System.in);}}9、模板

10、去掉形参提示符

十九、包

包的本质实际上就是创建不同的文件夹/目录来保存类文件

包的三大作用

1、区分相同名字的类

2、当类很多时,可以很好的管理类

3、控制访问范围

快速入门

包的命名规则

只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字或保留字

命名规范

一般是小写字母+小圆点一般是com.公司名.项目名.业务模块名

举例:com.sina.crm.user//用户模块com.sina.crm.order//订单模块com.sina.crm.utils//工具类注意事项和使用细节

2、import指令位置放在package的下面,在类定义前面,可以有多句且没有顺序要求

二十、访问修饰符

java提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问(范围)

1、公开级别:用public修饰,对外公开

2、受保护级别:用protected修饰,对子类和同一个包中的类公开

3、默认级别:没有修饰符号,向同一个包的类公开

4、私有级别:用private修饰,只有类本身可以访问,不对外公开

四种访问修饰符的访问范围

注意:子类可以访问父类的默认方法/属性的前提是在同一个包中

packagecom.first;publicclassA{publicintnum1=10;protectedintnum2=20;intnum3=30;privateintnum4=40;publicvoidAm(){System.out.println(num1+""+num2+""+num3+""+num4);}}packagecom.first;publicclassB{publicvoidBm(){Aa=newA();System.out.println(a.num1+""+a.num2+""+a.num3);}}packagecom.second;publicclassA{publicvoidAn(){com.first.Aa=newcom.first.A();System.out.println(a.num1);}}注意事项

1、修饰符可以用来修饰类中的属性,成员方法以及类

2、只有默认的和public才能修饰类!,并且遵循上述访问权限的特点

3、成员方法的访问规则和属性完全一样

二十一、封装介绍

1、封装的理解和好处

隐藏实现细节

可以对数据进行验证,保证安全合理

2、封装的实现步骤

将属性进行私有化private【使用户不能直接修改属性】

提供一个公共的(public)set方法,用于对属性判断并赋值

publicvoidsetXxx(类型参数名){//Xxx表示某个属性//加入数据验证的业务逻辑属性=参数名;}3、提供一个公共的(public)get方法,用于获取属性的值

public数据类型getXxx(){//可以加一些权限判断returnxx;}4、案例

请大家看一个小程序,不能随便查看人的姓名,年龄,工资等隐私,并对设置的年龄进行合理的验证

年龄合理就设置,否则给默认年龄18,必须在1-120

年龄,工资不能直接查看,name的长度在2-6字符之间

packagecom.encapsulation;publicclassShow{publicstaticvoidmain(String[]args){Personperson=newPerson();person.setName("HK9527");person.setAge(22);person.setSalary(9999.99);System.out.println(person.name);//这样会报错的!System.out.println(person.getName()+""+person.getAge()+""+person.getSalary());}}classPerson{privateStringname;privateintage;privatedoublesalary;publicStringgetName(){returnname;}publicvoidsetName(Stringname){if(name.length()>=2&&name.length()<=6){this.name=name;}else{System.out.println("输入的名称长度有误");this.name="NoOne";}}publicintgetAge(){returnage;}publicvoidsetAge(intage){if(age>=0&&age<=120){this.age=age;}else{System.out.println("输入的年龄范围不合法");this.age=-1;}}publicdoublegetSalary(){returnsalary;}publicvoidsetSalary(doublesalary){//在这可以加一些权限验证之类的this.salary=salary;}}5、快速设置set、get方法

6、封装与构造器

继承可以解决代码复用,让我们的编程更加靠近人类思维

packagecom.inherit;publicclassA{Stringname;intage;doublesalary;publicvoidinfo(){System.out.println(name+""+age+""+salary);}publicvoidcash(){System.out.println(name+"涨工资了");}}packagecom.inherit;publicclassBextendsA{publicvoidtest_b(){System.out.println("小学生"+name+"正在考试");}}packagecom.inherit;publicclassCextendsA{publicvoidtest_c(){System.out.println("大学生"+name+"正在考试");}}packagecom.inherit;publicclasstemp{publicstaticvoidmain(String[]args){Bb=newB();b.name="银角大王";//A类的共有属性nameb.age=20;//A类的共有属性ageb.salary=5000;//A类的共有属性salaryb.info();//A类的共有方法infob.test_b();//B类的特有方法test_bb.cash();//A类的共有方法cashCc=newC();c.name="金角大王";//A类的共有属性namec.age=30;//A类的共有属性agec.salary=8000;//A类的共有属性salaryc.info();//A类的共有方法infoc.test_c();//C类的特有方法test_cc.cash();//A类的共有方法cash}}1、继承细节问题

1>子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供的公共方法去访问

packagecom.details;publicclassfather{publicStringname;protectedintage;doubleheight;privatedoubleweight;publicvoidf1(){System.out.println("publicf1()方法被调用");}protectedvoidf2(){System.out.println("protectedf2()方法被调用");}voidf3(){System.out.println("f3()方法被调用");}privatevoidf4(){System.out.println("privatef4()方法被调用");}//定义访问privatedoubleweight;的public方法publicvoidsetWeight(doubleweight){this.weight=weight;}publicdoublegetWeight(){returnweight;}//定义调用privatevoidf4()的public方法publicvoiduseF4(){f4();}}packagecom.details;publicclassson{publicstaticvoidmain(String[]args){fatherfather=newfather();father.name="King";father.age=20;father.height=182.5;//father.weight;这样是访问不了的father.setWeight(65.5);System.out.println(father.getWeight());//这样可以访问father.f1();father.f2();father.f3();//father.f4();这样是访问不了的father.useF4();//这样可以访问}}2>子类必须调用父类的构造器,完成父类的初始化

packagecom.details;publicclassfather{father(){System.out.println("father()构造器被调用");}}packagecom.details;publicclasssonextendsfather{son(){//这里存在super();System.out.println("son()构造器被调用");}}packagecom.details;publicclasstest{publicstaticvoidmain(String[]args){sonson=newson();//运行结果://father()构造器被调用//son()构造器被调用}}3>当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器

如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过

packagecom.details;publicclassfather{//没有指定无参构造器,如果定义了构造器,那么原来的默认无参构造器就会失效,除非显式的定义一下father(Stringname,intage){System.out.println("father(Stringname,intage)构造器被调用");}}packagecom.details;publicclasssonextendsfather{son(Stringname,intage){super("tom",20);//在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作System.out.println("son(Stringname,intage)构造器被调用");}}packagecom.details;publicclasstest{publicstaticvoidmain(String[]args){sonson=newson("name",20);//运行结果://father(Stringname,intage)构造器被调用//son(Stringname,intage)构造器被调用}}4>如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)

packagecom.details;publicclassfather{//在父类中定义了三个构造器father(Stringname,intage){System.out.println("father(Stringname,intage)构造器被调用");}father(){System.out.println("father()构造器被调用");}father(Stringname){System.out.println("father(Stringname)构造器被调用");}}packagecom.details;publicclasssonextendsfather{//在子类中定义三个构造器,每个构造器都可以用super去指定不同父类的构造器son(Stringname,intage){super("tom",20);System.out.println("son(Stringname,intage)构造器被调用");}son(Stringname){super("tom");System.out.println("son(Stringname)构造器被调用");}son(){super();System.out.println("son()构造器被调用");}}packagecom.details;publicclasstest{publicstaticvoidmain(String[]args){sonson=newson("name",20);//运行结果://father(Stringname,intage)构造器被调用//son(Stringname,intage)构造器被调用}}5>super在使用时,必须放在构造器第一行(super只能在构造器中使用,不能再成员方法中使用)

6>super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7>java所有类都是Object类的子类,Object是所有类的父类

8>父类构造器的调用不限于直接父类!将一直往上追溯直到object类(顶级父类)

9>子类最多只能继承一个父类(指直接继承),即java中是单继承机制

思考:如何让A类继承B类和C类

【A继承B,B继承C】

10>不能滥用继承,子类和父类之间必须满足is-a的逻辑关系

2、继承原理的本质分析

查找时要按照查找关系来返回信息

1>首先看子类是否有该属性,如果子类有这个属性,并且可以访问,则返回信息

2>如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息)

3>如果父类没有就按照(2)的规则,继续找上级父类,直到Object

3、继承课堂练习

编写Computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回Computer的详细信息

编写PC子类,继承Computer类,添加特有属性【品牌brand】

编写exercise类,在main方法中创建PC对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法并打印输出信息

super代表父类的引用,用于访问父类的属性、方法、构造器

1>访问父类的属性,但不能访问父类的private属性

2>访问父类的方法,不能访问父类的private方法

3>访问父类的构造器,只能放在构造器里,且为第一句,只能出现一句!

packagecom.super_;publicclassfather{publicintage=10;protectedintheight=175;intsalary=8000;privateintweight=65;father(){System.out.println("father()构造器被调用");}father(intage){System.out.println("father(intage)构造器被调用");}publicvoidf1(){System.out.println("publicvoidf1()方法被调用");}privatevoidf2(){System.out.println("privatevoidf2()方法被调用");}}packagecom.super_;publicclasssonextendsfather{son(){//访问父类构造器的语法:super(参数列表);super(20);//只能放在构造器里,且为第一句,只能出现一句!System.out.println("son()构造器被调用");}publicvoids1(){intage=super.age;//访问属性的语法:super.属性名;intheight=super.height;intsalary=super.salary;//super.weight是私有属性,所以访问不了System.out.println(age+""+height+""+salary);}publicvoids2(){super.f1();//访问方法的语法:super.方法名(参数列表);//super.f2()是私有方法,所以访问不了}}packagecom.super_;publicclassrun{publicstaticvoidmain(String[]args){sonson=newson();son.s1();son.s2();}}1、super细节

1>当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super;如果没有重名,使用super、this、直接访问是一样的效果

2>super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;

二十四、方法重写/覆盖override

方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、形参列表一样,那么就说子类的这个方法覆盖了父类的方法

packagecom.super_;publicclassfather{publicvoidm1(){//方法名称、返回类型、型参列表都一样System.out.println("father类的publicvoidm1()被调用");}}packagecom.super_;publicclasssonextendsfather{publicvoidm1(){//方法名称、返回类型、型参列表都一样System.out.println("son类的publicvoidm1()被调用");}}1、方法重写的细节

方法重写也叫方法覆盖,需要满足下面的条件

1>子类的方法的形参列表、方法名称,要和父类方法的形参列表方法名称完全一样

2>子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类(比如父类返回类型是Object,子类方法返向类型是String,String是Object的子类)

packagecom.super_;publicclassfather{publicAAAm1(){returnnull;}}classAAA{//定义AAA类}classBBBextendsAAA{//BBB是AAA的子类}packagecom.super_;publicclasssonextendsfather{publicBBBm1(){//方法名称、返回类型BBB是AAA的子类、型参列表都一样returnnull;}}3>子类方法不能缩小父类方法的访问权限public>protected>默认>private

2、方法的重载和重写比较

二十五、多态

方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承基础之上的

1、多态详解

方法的多态:方法的重写和重载就体现多态

对象的多态

1>一个对象的编译类型和运行类型可以不一致

2>编译类型在定义对象时,就确定了,不能改变

3>运行类型是可以变化的

4>编译类型看定义时=号的左边,运行类型看=号的右边

5>多态的前提是两个对象(类)存在继承关系

2、向上转型

1>本质:父类的引用指向了子类的对象

2>语法:父类类型引用名=new子类类型();

3>特点:编译类型看左边,运行类型看右边

可以调用父类中的所有成员(需遵守访问权限)、不能调用子类中特有成员、最终运行效果看子类的查找顺序

packagecom.up;publicclassfather{publicvoideat(){System.out.println("father的eat方法");}publicvoidrun(){System.out.println("father的run方法");}privatevoidcry(){System.out.println("father的cry方法");}}packagecom.up;publicclasssonextendsfather{publicvoideat(){//重写了father的eat方法System.out.println("son的eat方法");}publicvoiddrink(){//son的特有方法System.out.println("son的drink方法");}}packagecom.up;publicclassrun{publicstaticvoidmain(String[]args){fathertemp=newson();//父类的引用指向了子类的对象,叫向上转型temp.eat();//输出结果:son的eat方法temp.run();//输出结果:father的run方法//temp.drink();//这样是会报错的//temp.cry();//这样是会报错的}}向上转型细节

1>temp这个变量引用可以调用father类的所有属性和方法,但是要遵守权限,father类的private的方法就不能调用

3>temp调用运行方法时最终的运行效果要看son类(运行类型)的查找规则,由java这个程序运行,即调用方法时按照从子类向父类的顺序进行查找

总结一句话:调用方法看编译类型,执行顺序看运行类型

3、向下转型

1>语法:子类类型引用名=(子类类型)父类引用;

2>只能强转父类的引用,不能强转父类的对象

3>要求父类的引用必须指向的是当前目标类型的对象

publicclassrun{publicstaticvoidmain(String[]args){Animaltemp=cat();Dogdog=(Dog)temp;//会报错,因为原来的temp是一只羊,你不能把temp强转成一只狗}}4>当向下转型后,可以调用子类类型中所有的成员

经过向下转型之后的son指向的也是son()这个对象,此时son的编译类型是son,所以可以调用子类类型的所有成员,因为son类还继承了father类,所以son也可以调用father类的成员

4、多态注意事项

1>属性没有重写之说,属性的值看编译的类型

packagecom.up;publicclassrun{publicstaticvoidmain(String[]args){fathertemp=newson();System.out.println(temp.age);//输出结果:50System.out.println(((son)temp).age);//输出结果:25}}classfather{intage=50;}classsonextendsfather{intage=25;}2>instanceOf比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型

packagecom.up;publicclassrun{publicstaticvoidmain(String[]args){Stringname="King";fathertemp=newson();System.out.println(tempinstanceofson);//输出结果:trueSystem.out.println(tempinstanceoffather);//输出结果:trueSystem.out.println(nameinstanceofObject);//输出结果:true}}classfather{intage=50;}classsonextendsfather{intage=25;}3>向上转型的特殊写法

packagecom.up;publicclassrun{publicstaticvoidmain(String[]args){sons_temp=newson();fatherf_temp=s_temp;//向上转型,相当于fatherf_temp=newson();//注意:s_temp和f_temp是指向同一个对象的}}classfather{intage=50;}classsonextendsfather{intage=25;}5、练习题

packagecom.up;publicclassrun{publicstaticvoidmain(String[]args){Subs=newSub();System.out.println(s.count);//20属性的值看编译的类型s.display();//20Baseb=s;System.out.println(b==s);//两个对象比较的是地址trueSystem.out.println(b.count);//10属性的值看编译的类型b.display();//20向上转型调用运行方法时最终的运行效果要看运行类型的查找规则,由java这个程序运行,即调用方法时按照从子类向父类的顺序进行查找}}classBase{intcount=10;publicvoiddisplay(){System.out.println(this.count);}}classSubextendsBase{intcount=20;publicvoiddisplay(){System.out.println(this.count);}}6、动态绑定机制

1>当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

二十六、多态数组

数组的定义类型为父类类型,里面保存的实际元素类型为子类类型

packagecom.ployarr;publicclassrun{publicstaticvoidmain(String[]args){Object[]array={"King",20,52.10,'A'};for(inti=0;i

现有一个继承结构如下:

要求创建1个Person对象、2个Student对象、2个Teacher对象,统一放在数组中,并调用每个对象的say方法,并且想办法调用Student对象和Teacher对象的私有方法

方法定义的形参类型为父类类型,实参类型允许为子类类型,应用实例:前面的主人喂动物

应用实例:

定义员工类Employee,包含姓名和月工资[private],以及计算年工资getAnnual的方法

普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法,普通员工类多了work方法,普通员工和经理类要求分别重写getAnnual方法

测试类中添加一个方法showEmpAnnual(Employeee),实现获取任何员工对象的年工资,并在main方法中调用该方法[e.getAnnual()]

测试类中添加一个方法,testWork,如果是普通员工,则调用work方法,如果是经理,则调用manage方法

==是一个比较运算符

1、==既可以判断基本类型,又可以判断引用类型

2、==如果判断基本类型,判断的是值是否相等(示例:inti=10;doubled=10.0;)

3.、==如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象

packagecom.com;publicclassequals_{publicstaticvoidmain(String[]args){Integernum1=newInteger(5);Integernum2=newInteger(5);//==如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象System.out.println(num1==num2);//falseintnum3=50;doublenum4=50.0;//==如果判断基本类型,判断的是值是否相等System.out.println(num3==num4);//true}}4、equals是Object类中的方法,只能判断引用类型

5、equals默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等

//Object类的equals方法publicbooleanequals(Objectobj){return(this==obj);}//String类重写了equals方法publicbooleanequals(ObjectanObject){if(this==anObject){returntrue;}if(anObjectinstanceofString){StringaString=(String)anObject;if(coder()==aString.coder()){returnisLatin1()StringLatin1.equals(value,aString.value):StringUTF16.equals(value,aString.value);}}returnfalse;}//Integer类重写了equals方法publicbooleanequals(Objectobj){if(objinstanceofInteger){returnvalue==((Integer)obj).intValue();}returnfalse;}packagecom.com;publicclassequals_{publicstaticvoidmain(String[]args){Objecttemp=newObject();Objecttest=temp;//equals默认判断的是地址是否相等System.out.println(temp.equals(test));//trueStringstr="King";Stringstr1="King";Stringstr2="mark";//子类中往往重写该方法,用于判断内容是否相等System.out.println(str.equals(str1));//trueSystem.out.println(str.equals(str2));//false}}备注:ctrl+B可以查看当前的方法的JDK源码

应用实例:判断两个tools对象的内容是否相等,如果两个tools对象的各个属性值都一样,则返回true,反之false

packagecom.equalshomework;publicclassPerson{publicstaticvoidmain(String[]args){toolsa=newtools("zrh",20,'男');toolsb=newtools("zrh",20,'男');System.out.println(a.equals(b));}}classtools{privateStringname;privateintage;privatechargender;publictools(Stringname,intage,chargender){this.name=name;this.age=age;this.gender=gender;}publicbooleanequals(Objectobj){//重写了equals方法if(this==obj){//==如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象returntrue;}elseif(objinstanceoftools){toolst=(tools)obj;//向下转型,为了可以拿到对象的属性值returnthis.name.equals(t.name)&&this.age==t.age&&this.gender==t.gender;}returnfalse;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicchargetGender(){returngender;}publicvoidsetGender(chargender){this.gender=gender;}}二十九、hashCode方法

1、提高具有哈希结构的容器的效率

2、两个引用,如果指向的是同一个对象,则哈希值肯定是一样的

3、两个引用,如果指向的是不同对象,则哈希值是不一样的

4、哈希值主要根据地址号来的,不能完全将哈希值等价于地址

5、在集合中hashCode如果有需要的话,会进行重写

packagecom.hashCode;publicclasshashCode{publicstaticvoidmain(String[]args){testtest1=newtest();testtest2=newtest();testtest3=test1;System.out.println(test1.hashCode());//1239731077System.out.println(test2.hashCode());//557041912System.out.println(test3.hashCode());//1239731077}}classtest{}三十、toString方法

基本介绍

默认返回:全类名+@+哈希值的十六进制

1、子类往往重写toString方法,用于返回对象的属性信息

2、重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString形式.

3、当直接输出一个对象时,toString方法会被默认的调用,比如System.out.printIn(monster);就会默认调用monster.toString()

//查看Object的toString方法publicStringtoString(){returngetClass().getName()+"@"+Integer.toHexString(hashCode());}packagecom.toString_;publicclasstoString_{publicstaticvoidmain(String[]args){catcat=newcat();System.out.println(cat.toString());//com.toString_.cat@49e4cb85mastermaster=newmaster();System.out.println(master.toString());//master{name='King',age=20}//当直接输出一个对象时,toString方法会被默认的调用System.out.println(cat);//等价于System.out.println(cat.toString());System.out.println(master);//等价于System.out.println(master.toString());}}classcat{}classmaster{privateStringname="King";privateintage=20;@OverridepublicStringtoString(){return"master{"+"name='"+name+'\''+",age="+age+'}';}}三十一、finalize方法

1、当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作

2、什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法

3、垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制

我们在实际开发中,几乎不会运用finalize,所以更多就是为了应付面试

packagecom.finalize_;publicclassfinalize_{publicstaticvoidmain(String[]args){carcar=newcar("宝马");car=null;//这时car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象//在销毁对象前,会调用该对象的finalize方法//程序员就可以在finalize中,写自己的业务逻辑代码(比如释放资源:数据库连接,或者打开文件..)//如果程序员不重写finalize,那么就会调用Object类的finalize,即默认处理System.gc();System.out.println("程序执行完毕");}}classcar{Stringname;publiccar(Stringname){this.name=name;}@Overrideprotectedvoidfinalize()throwsThrowable{System.out.println("释放资源……");}}//执行结果://释放资源……//程序执行完毕三十二、断点调试

F7(跳入方法内)

alt+shift+F7(强制进入)

F8(逐行执行代码)

shift+F8(跳出方法)

F9(resume,直接执行到下一个断点)

Ideadebug如何进入Jdk源码

解决方法1:使用forcestepinto:快捷键alt+shift+F7

解决方法2:配置一下就好了

点击Setting-->Build,Execution,Deployment-->Debugger-->Stepping

把Donotstepintotheclasses中的java.*,javax.*取消勾选

三十三、零钱通案例

工具集类为将事先用到的方法都先写好,在service类里直接调用即可,例如:接受用户输入+输入正确值判断等

我们在拿到需求进行分析的时候,应该从用户的角度去进行分析,在代码实现的时候应该从下往上去实现

packagetest;publicclasstest{publicstaticvoidmain(String[]args){run.A();//因为A方法为static,所以不需要创建对象就可以直接调用//运行结果:test包下的static的A方法}}packagetest;publicclassrun{publicstaticvoidA(){System.out.println("test包下的static的A方法");}}

THE END
1.东方财富网旗下彩票资讯网站七乐彩开奖页面奖项中奖注数单注奖金(元)中奖条件 一等奖 2 359,455 中7+0 二等奖 10 10,270 中6+1 三等奖 92 2,232 中6+0 四等奖 338 200 中5+1 五等奖 3,597 50 中5+0 六等奖 6,002 10 中4+1 七等奖 40,026 5 中4+0 本期总奖金额 1,534,554元https://caipiao.eastmoney.com/Result/Category/qlc?id=2024111
2.新快报新快报讯 记者陆妍思 通讯员杨智报道 中国福利彩票双色球第2024122期开奖中,全国共中出一等奖10注,其中1注花落惠州市博罗县龙溪镇44080451福彩销售站点。中奖彩民罗先生(化姓)凭借一张“6+2”4元复式自选票幸运揽获当期一等奖1注,单票中奖奖金超过690万元。 https://ep.ycwb.com/epaper/xkb/html/2024-11/28/content_1510_678821.htm
3.六+彩资料免费大全,实地验证策略具体FKB50.756理想版2. 跟随专业彩票分析师 在选择资料的过程中,一些专业分析师的言论与建议具有较高的参考价值。借助专家的深度分析,彩民可以从中提炼出有效的信息,形成自己的购彩思路。 3. 实际观察彩票热度 在参与线下购买彩票的过程中,可以观察体验金彩票的热度和变化,如某些号码在娱乐场所或社交圈子中的受欢迎程度。这类信息可以反https://subenyuanpco.com/post/21838.html
4.24139期[小黑豆]大乐透精选6+2复式后区杀三码 05,06,11 05,08,09 对2码 后区杀一码 11 05 对1码大乐透复式推荐 玩法 本期推荐 上期推荐 出奖情况 复式12+6 05,11,16,2024,26,27,2931,32,33,35+02,03,08,0910,12 03,05,09,1418,23,24,2627,28,30,33+01,02,04,0611,12 中九等奖 复式12+3 05,11,16,2024,26,https://www.ydniu.com/info/dlt/zjtj/716520241128.html
5.新澳门六开奖结果今天,最佳精选解析说明旗舰版91.280特等奖:中6个正码,奖金高达数百万澳门币。 一等奖:中5个正码加特别号码,奖金数十万澳门币。 二等奖:中5个正码,奖金数万澳门币。 三等奖:中4个正码加特别号码,奖金数千澳门币。 四等奖:中4个正码,奖金数百澳门币。 五等奖:中3个正码加特别号码,奖金数十澳门币。 http://www.xinyuplay.cn/post/8549.html
6.双色球复式9+1中6+0多少钱奖金双色球双色球复式9+1中6+0多少钱奖金 双色球复式9+1中6+0多少钱奖金,接下来唯彩看球小编给大家介绍一下中国福利彩票双色球的更多玩法及双色球的专家资讯推荐方案,如果你对此也感兴趣的话,赶紧过来看看吧。 双色球精选https://vipc.cn/tags/shuangseqiufushi9+1zhong6+0duoshaoqianjiangjin
7.我不是猪头攻略大全答案:0本,因为没有桌子。 4、如果1=10,2=20,3=30,4=40,那么10=多少? 答案:1 解析:既然1=10了,那么当然10=1了。 5、用以下物品敲打别人的脑袋谁最疼? 答案:脑袋(点击题目中的“脑袋”两个字即可,所有图片都是错误答案哦!) 6、制作一个禁止停车的标志 https://www.9game.cn/news/9922231.html
8.双色球选号技巧方法一个玩了7年的老彩名民的心得选6+1中 5+0或中 4+1 五 等 奖 单注奖金额固定为10元 选6+1中 4+0或中 3+1 六 等 奖 单注奖金额固定为5元 选6+1中 2+1或中 1+1或中 0+1 引言:明确双色球中奖概率,是你挺进500W的第一步 一等奖中6+1概率1/17721088 二等奖中6+0概率15/17721088 https://www.360doc.cn/document/37274554_600075746.html
9.中粮集团粮油加盟加盟中粮集团粮油需要多少钱?如何加盟?2016年福临门连续6年、蒙牛连续2年入选中国最权威的BrandZ?最具价值中国品牌100强,长城葡萄酒获亚洲葡萄酒质量大赛金奖,证明了消费者和行业对中粮产品的高度认可。 2016年,中粮将品牌建设纳入“十三五”发展规划,从战略高度予以筹划推进,积极探索新的发展策略,进一步扩大一批重点产品和知名品牌的市场占有率和行业影响力https://www.jiamengfei.com/xm/101879