计算机语言的分类:
机器语言汇编语言高级语言 第一代:C语言,面向过程为编程思想,它是唯一一门可以直接操作计算机硬件的语言。第二代:C++,面向对象为编程思想,没有默认的垃SEO靠我圾回收机制(GC)。第三代:Java,面向对象为编程思想,有默认的GC。第四代:自然语言,面向问题为编程思想。为什么要学习Java语言?
Java是使用最广泛,且用法简单的语言。
JSEO靠我ava是一门强类型的语言(对数据类型的划分很精细)。
Java有非常严谨的异常处理机制。
Java提供了对于大数据的基础性支持。hadoop的底层使用java编写。
1995年由SUN公司推出,Java之父SEO靠我:詹姆斯·高斯林,SUN公司在2009年被Oracle收购。
开跨两多面:开源跨平台,多线程多态面向SEO靠我对象。
开源 源代码是开源的。 跨平台 用Java编写的程序可以在不同的操作系统上运行。原理:有JVM保证Java程序的跨平台性,但是JVM本身不跨平台。:Java虚拟机(Java Virtual Machine) 作用:用来保证JavaSEO靠我程序跨平台,但是JVM本身不能跨平台
Library->Java->JavaVirtualMachines->jdk1.8.0_301.SEO靠我jdk
目录解释 bin:存放编译器和工具db:存放数据include:编译本地方法jre:java运行时文件lib:类库文件src.zip:源代码目的:在任何路径下都可以使用JSEO靠我DK提供的工具。例如java,javac。
vim ~/.bash_profile添加变量名,变量值。
export JAVA_HOME=/Library/Java/JavaVirtualMachinesSEO靠我/jdk1.8.0_301.jdk/Contents/Home export CLASSPAHT=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/toolSEO靠我s.jar export PATH=$JAVA_HOME/bin:$PATH验证:
在terminal中输入:java -version程序的开发:编写-SEO靠我>编译->执行
编写源代码:在后缀为.java的文件中编写。编译:把我们能看懂的文件编译成计算机能看懂的文件。 .java -> .class(字节码文件,给计算机看的) 运行:计算机运行字节码文件,用SEO靠我过java指令实现。 javac HelloWorld.java会产生一个HelloWorld.class文件
java HelloWorld #由于设计规范,此处无需后缀,实际执行.cSEO靠我lass文件显示运行结果
方式:新建一个JavaSE项目,每天新增一个模块(推荐)
创建一个空的项目
在project选项SEO靠我中设置SDK和Project Language Level
在该项目下创建Day01模块Modules->Java->Moduel SDK设置
在Day01模块的src(源代码包)下创建:自定义包在自定义SEO靠我包下创建Java类
在Java类中写代码
运行
关键字:被java赋予了特殊含义的单词。
特点 关键字有纯英文小写字母组成常用开发工具会highlight关键字在程序的执行中,其值不能发生改变的量。
在程序的执行中,其值可以在某个范围内发SEO靠我生改变的量。从本质上讲,变量其实是内存中的一小块区域,例如:
商品的价格(1元,5元,100元)钟表的时间(5点,6点,10点半)人的年龄(10岁,20岁,50岁)程序员生涯的职位(开发工程师,开发经理SEO靠我,项目经理,CTO)java中要求每个变量每次只能保存一个数据,而且必须要明确保存数据的数据类型。
变量的值在某一个范围内发生变化。(通过数据类型来限制)
能找到这一块区域。(通过变量名SEO靠我实现)
区域内必须有数据。(初始化值)
形式:
数据类型 变量名 = 初始化值;java是一门强类型语言。其对数据的划分很精细。
整型byte1个字节-128~127short2个字节int4SEO靠我个字节long8个字节浮点型float4个字节double8个字节字符型char2个字节布尔型boolean1个字节 byte类型的取值范围是:-128~127,char类型的取值范围SEO靠我是0~65535默认的整型是int,默认的浮点是double定义long型时,数据后面要加字母L定义float型时,数据后面要加字幕F方式一:直接初始化变量
int a = 10;方式二:先声明,后赋值SEO靠我
int a; a = 10;标识符就是用来给类SEO靠我,接口,方法,变量,包等起名字的规则。
hust.edu.cn -> cn.edu.hust
小类型转大类型,会自动提升为大类型,运算结果时大类型。
doubSEO靠我le a = 10; int和double相加,为doublechar和int相加,为intboolean和int相加,报错 转换规则 范围小的类型向范围大的类型提升SEO靠我,byte, short, char运算时直接提升为intboolean类型不能参与数值转换手动将大类型转换成小类型,运算结果是小类型
short s = 1; sSEO靠我 = (short)(s+1); System.out.println(s);//结果为2,short类型Java中对于常量,有常量优化机制。
针对于byte类型:SEO靠我 常量相加:常量相加会直接运算,然后判断结果在不在左边的数据范围内变量相加:会自动提升数据类型,然后运算,提升规则byte, short, char -> int -> long -> float -SEO靠我> double
针对于string类型: 后边API解释运算符:连接常量和变量的符号。
表达式:用运算符把常量或者变量连接起来符合java语法的式子。不同运算符连接的表达式体现的是不同类型SEO靠我的表达式。
整数相除,结果还是整数。除非有浮点型参与。
加号运算符在字符串之间表示连接。System.out.println("Hello" + 5 + 5)//Hello55 SEO靠我 System.out.println("Hello" + (5 + 5))//Hello10 System.out.println(5 + 5 + "Hello" + 5 +SEO靠我 5)//10Hello55i++,先运算后自增
++i,先自增后运算
++和–都隐含了强制类型转换。byte a = 1; a = a++;//包含了强制类型转SEO靠我换,等价于下行代码 a = (byte)(a + 1);基本的赋值运算符:=
拓展的赋值运算符:+=, -=, *=, /=, %=a += b; 等价于 a = aSEO靠我 + b;
赋值运算符的左边不能为常量。
拓展的赋值运算符默认包含了强制转换。byte a = 1; a += 1;//包含了强制类型转换,等价于下行代码 a = byteSEO靠我(a + 1);==, !=, >, <, <=, >=,返回true或者false
&, |, !,^异或
短路逻辑运算符 符号作用说明&&短路与SEO靠我作用和&相同,但是有短路效果,前面如果出现false,后面不执行||短路与作用和|相同,但是有短路效果,前面如果出现true,后面不执行(关系表达式)? 表达式1 : 表达式2;
首SEO靠我先执行关系表达式,如果true执行表达式1,如果false执行表达式2
写在类上面,package下面
import java.util.ScanneSEO靠我r; 创建Scanner类的对象 Scanner sc = new Scanner(System.in); 通过Scanner类的nextInt()SEO靠我方法接收用户录入的数据 int a = sc.nextlnt();某些代码在满足特定条件下才会执行;有些代码在满足特定条件下重复执行。这些都需要用到流程控制SEO靠我语句。
代码按照从上往下从左往右的顺序依次逐行执行。是SEO靠我java程序的默认结构。
System.out.println(10+10+"Hello"+10+10);20Hello1010
if语句一般用为范围的判断
if语句SEO靠我(单分支)单分支结构一般用来判断一种情况 if(条件语句){ //语句体; } if.else语句(双SEO靠我分支)
一般用来判断两种情况 if(条件语句){ //语句体1; }else{ //语句体2; } ifSEO靠我.else if语句(多分支) if(条件语句1){ //语句体1 }else if(条件语句2){ //语句体2 }eSEO靠我lse if(条件语句3){ //语句体3 } ··· else{ //语句体 } 1SEO靠我5.4.2 switch语句一般用于固定值判断
switch(表达式){ //表达式的取值类型:byte, short, int, char, JDK5以后可以是枚举,JDK7以后可以是StringcaSEO靠我se 值1: //case后面跟的是要和表达式进行比较的值语句体1; //语句体可以使一条或者多条语句break; //break表示中断,结束switch语句case 值2:语句体2;break;cSEO靠我ase 值3:语句体3;break;···default: //default表示所有情况都不匹配时执行,写在任何位置都是最后才执行语句体n;break; }case穿透:
在switcSEO靠我h语句中,如果case后面不写break,将出现case穿透现象,也就是不会在判断下一个case的值,直接向后运行,知道遇到break,或者整体switch结束。switch(month){case SEO靠我1:case 2:case 12:String season = "Winter";break;··· }思考题:break关键字可以省略吗?
答:最后一个分支的break可以省略,其他SEO靠我分支如果省略break可能对结果有影响。for循环
一般适用于循环次数固定的情况。while循环
一般适用于循环次数不固定的情况。do.while循环
实际开发中基本不用,适用于先执行一次SEO靠我然后判断的情况。 15.5.1 for循环 for(初始化条件;判断条件;控制条件){//循环体 }先执行初始化条件,然后执行判断条件,查看结果trueSEO靠我还是false,如果true执行循环体,执行控制条件。
15.5.2 while循环 初始化条件; while(判断条件){//循环体;//控制条件; }SEO靠我 15.5.3 do.while循环 初始化条件; do{循环体;控制条件; }while(判断条件);for和SEO靠我其他两个循环的区别
for循环结束后,初始化条件就不能继续使用了。而while和dowhile可以。do.while和其他两个循环的区别
先执行一次再判断,而其他两个循环是先判断再执行。用得最多的是for循环的嵌套
for(初始条件;判断条件;控制条件){ /SEO靠我/外循环for(初始条件;判断条件;控制条件){ //内循环//循环体} }Math类似Scanner,是Java提供好的API(Application ProSEO靠我gramming Interface),内部提供了产生随机数的工程。
如果需要同时存储多个同类型的数据,我们可以通过数组来实现。
数组就是用来存储多个同类型元素的容器。初始化数组不可同时给定长度和初值。
int[] arr = new int[3];
解释:数据类型:数组中存储元素的数据类型。如SEO靠我这里的int说明数组中只能存储int类型的数据。[]:表示是数组数组名:类似于变量名,要符合小驼峰new:指创建数组对象内SEO靠我存是计算机中的重要元件,也是临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘当中的,在硬盘中的程序是不会运行的,必须放入内存中才能运行,运行完毕后会清空内存。
即:Java虚拟机要运行程序,必须SEO靠我要对内存进行空间的分配和管理。为例提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
JVM的内存划分栈:存储局部变量以及所有代码执行的。
局部变量:定义在方SEO靠我法中,或者方法声明上的变量。
特点:先进后出堆:存储所有new出来的内容,即对象
特点:堆中的内容会在不确定的时间被GC回收。方法区:存储字节码文件。
字节码文件:后缀为.class的文件。本地方法区:和系SEO靠我统相关,了解即可。寄存器:和CPU相关,了解即可。
内存图解,示意图(并不严格) public class ArrayDemo{public static void main (StriSEO靠我ng[] args){int[] arr = new int[3];System.out.println(arr[0]);System.out.println(arr);//打印的是存储地址} SEO靠我 } 17.3.2 两个数组的内存图 public class StoragePic {public static void main(String[] aSEO靠我rgs) {int[] arr = new int[3];arr[0] = 11;System.out.println(arr[0]);System.out.println(arr[1]);SysteSEO靠我m.out.println(arr);int[] arr2 = {1, 2};arr2[1] = 22;System.out.println(arr2[1]);System.out.println(aSEO靠我rr2);} }产生原因:访问了数组中不存在的索引
解决方案:访问数组中存在的索引即可 17.4.2 空指针异常产生原因:访问了空对SEO靠我象
解决方案:对对象赋具体的值方法SEO靠我也叫函数,是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。
图解
同一个类中,出现方法名相同,但是参数列表不同的两个或多个的方法时,称为方法重载,方法重载与方法的修SEO靠我饰符、返回值的数据类型无关。
参数列表不同分为两种类型: 参数的个数不同对应参数的数据类型不同形参如果是基本类型,形参的改变不影响实参。
public class SEO靠我demo01 {public static void main(String[] args) {int num = 100;change(num);System.out.println(num);//SEO靠我打印结果仍然是100}public static void change(int num){num = 200;} }引用类型作为参数时,形参的改变直接影响实参(String类型除外,SEO靠我String类型当作形参使用时,用法和基本类型一致,后续API详解)
public class demo02 {public static void main(String[] args) {int[]SEO靠我 arr = {10, 20, 30};System.out.println(arr[1]);//打印结果为20change(arr);System.out.println(arr[1]);//打印结SEO靠我果为200}public static void change(int[] arr){arr[1] = 200;} }步骤:
加断点,哪里不会点哪里运行加了断点的程序SEO靠我,选择debug开始调试
debugger:看代码执行到哪里了
console:控制台,查看程序运行结果
variable:查看变量的变化过程进行下一步
F7:逐过程调试
F8:逐行调试
F9:逐断点调试删除断点SEO靠我
方式一:一个一个删除
方式二:批量删除,选择breakpoints(双红点),移除断点即可明确目的分析过程通过代码一步步实现
以上每一个步骤我们都是参与者,需要面SEO靠我对具体的每一个步骤和过程,
代表语言:C当需求单一且简单,一步一步操作没有问题效率也挺高。但是如果需求更改、增多,把这些步骤和功能进行封装。封装时根据不同的功能进行不同的封装,功能类似SEO靠我的用一个类封装在一起。使用的时候找到对应的类。
思想特点:是一种符合我们思考习惯的思想可以将复杂的事情简单化让我们从执行者变成了指挥者
小结
面向对象是一种编程思想,它是基于面向过程的,强调的是以对象为基础SEO靠我完成各种操作。面试题:什么是面向对象?
思路:概述,思想特点,举例,总结我们是如何表示现实世界的事物的呢?
Java语言是用来描述现实世界事物的,最基本的单位是:类类:是一个抽象的概念,看不SEO靠我见也摸不着,它是属性和行为的集合对象:类(该事物)的具体体现,实现属性(成员变量) 属性指的就是事物的描述信息(名词)属性在Java中被称为成员变量行为(成员方法) 用SEO靠我来指事物能够做什么也叫成员方法,和以前定义方法类似,先不写static举例
类:学生;大象
对象:张三,23;北京动物园叫图图的大象
属性(成员变量):年龄,性别,专业;年龄,性别,品种
行为(成员方法):学SEO靠我习、吃饭、睡觉;吃饭、睡觉、迁徙定义类其实就是定义类的成员(成员变量和成员方法)
成员变量: 和以前定义变量是一样的,只不过位置发生了改变,写到类中,方法外成员变量SEO靠我还可以不用赋值,因为它有默认值 成员方法: 和以前定义方法是一样的,只不过把static关键字去掉这点记忆即可,后面再讲解static关键字的用法 puSEO靠我blic class student {//属性(成员变量):姓名,年龄,性别String name;int age;String sex;//行为(成员方法):学习,吃饭,睡觉public voidSEO靠我 study(){System.out.println("学习");}public void eat(){System.out.println("吃饭");}public void sleep(){SSEO靠我ystem.out.println("睡觉");} }类的使用就是使用类中定义的成员(成员变量和成员方法)
格式 创建该类的对象
类名 对象名 =SEO靠我 new 类名();通过对象名.的形式,调用类中的指定成员
//成员变量
对象名.成员变量
//成员方法
对象名.成员方法(参数列表中各数据类型对应的值) 示例 public SEO靠我class StudentTest {public static void main(String[] args) {Student s = new Student();System.out.prinSEO靠我tln(s.name);//null(默认值)System.out.println(s.age); //0(默认值)System.out.println(s.sex); //null(默认值)s.naSEO靠我me = "Nick";s.age = 22;s.sex = "Male";System.out.println(s.name);//NickSystem.out.println(s.age); //SEO靠我22System.out.println(s.sex); //Male} }成员变量:定义在类中,方法外的变量。局部变量:定义在方法中或者方法声明上的变量。
他们的区别如下: 定义位置不同 成员变量定义在类中,方法外局部变量定义在方法中或者方法SEO靠我声明上 在内存中的存储位置不同 成员变量:存储在堆内存局部变量:存储在栈内存 生命周期不同 成员变量随着对象的创建而存在,随着对象的消失而消失局部变量随着方法的调用而存在,随着方法的调用完毕而消失 初SEO靠我始化值不同 成员变量有默认值局部变量没有默认值,必须定义赋值才能使用上述的代码中,我们可以任意的设置属性的值,包括我们可以设置一些非法值,例如把年龄设置成负数,这样做程序就容易出问题,针对这SEO靠我种情况,我们可以通过private关键字来优化。
private是一个关键字,也是访问权限修饰符的一种,它可以用来修饰类的成员(成员变量和成员方法)
被private修饰的内SEO靠我容只能在本类中直接使用。应用场景 在实际开发中成员变量基本上都是用private关键字来修饰的如果明确知道类中的某些内容不想被外部访问 public class PhoSEO靠我ne{private int age;public int getAge(){return age;}public void setAge(int a){age = a;} }封装是面向对象编程思想的三大特征之一,所谓的封装就是隐藏对象的属性和细节,仅对外提供一个公共的访问方式。
面向对象的三大特征:封装、继承、多态
隐藏:private修饰符
公共访问方式:publSEO靠我ic成员方法
原则把不需要对外提供的内容都隐藏起来把属性隐藏,并提供公共方法对其访问
解释:成员变量都用private修饰,并提供对应的公共方法,其他都用public修饰
好处提高代码的安全性:由privaSEO靠我te保证提高代码的复用型:由方法保证this表示本类当前对象的引用,即谁调用,this就代表谁
用来解决局部变量和成员变量重名的问题
使用变量的原则:就近原则(局部位置有就使用,没SEO靠我有就去本类的成员位置找,有就使用,没有就报错)(不严谨,还会去父类找)package cn.edu.hust.demo;public class Student {int x = 1;public vSEO靠我oid method(){int x = 2;System.out.println(this.x);System.out.println(x);} } packageSEO靠我 cn.edu.hust.demo;public class StudentTest {public static void main(String[] args) {Student s = new SEO靠我Student();s.method();//1,2 this.x等价于s.xs.x = 10;s.method();//10,2} }加入this关键字后标准额度JavaBean类的SEO靠我编写方法
public class Student {private String name;private int age;public void setName(String name){this.SEO靠我name = name;}public String getName(){ // return this.name;//能不多写就不写return name;}public void SEO靠我setAge(int age){this.age = age;}public int getAge(){return age;}public void study(){System.out.printSEO靠我ln("好好学习,天天向上!");}public void sleep(){System.out.println("为了保证精力,请好好休息!");} } publiSEO靠我c class StudentTest {public static void main(String[] args) {Student s = new Student();s.setAge(22);SEO靠我s.setName("Nick");System.out.println(s.getAge());System.out.println(s.getName());s.study();s.sleep()SEO靠我;} }构造方法是用来创建对象的,可以给对象的各个成员变量赋值。
构造方法就是用来快速对对象的各个属性赋值的。
格式构造方法名必须和类名完全一致构造方法没有返回值类型,vSEO靠我oid也不用构造方法没有具体的返回值,但是可以写return(实际开发中一般不写)构造方法可以重载 public 类名(参数类型 参数名1,参数类型 参数名2){//给对象的各个属性复SEO靠我制 }注意事项
如果我们没有给出构造方法,系统将给出一个默认的空参构造如果我们给出了构造方法,系统不会给默认的构造方法
给成员变量赋值有两种方式setXXX(),不会创建新对象构造方法,会SEO靠我创建新对象 public class Student{private String name;private int name;public Student(String name, SEO靠我int age){this.name = name;this.age = age;} } public class StudentTest{String name =SEO靠我 "Nick";int age = 22;Student s = new Student(name, age); }JavaBean也可以称为实体类,其对象可SEO靠我以用于在程序中封装数据。
标准JavaBean必须满足如下要求:
成员变量全部用private修饰提供成员变量对应的getter和setter方法必须提供一个无参构造器,有参构造器可写可不写多个SEO靠我类中存在相同属性和行为时,将这些内容抽取到单独的一个类中,那么这个类就无需再定义这些属性和行为了,只要继承那个类即可。这个关系就叫继承。
有了继承以后,我们在定义一个类的时候,可以在一个已经存在的类的基SEO靠我础上,还可以定义新的成员。
格式 public class 类A extends 类B{ //A是子类,B是父类}好处:
提高了代码的复用型
提高了代码的可维护性
让类与类之间产生关系,是多态的前提
弊端:
让类与SEO靠我类之间产生关系,也就让类的耦合性增强了。开发原则:高内聚,低耦合。内聚指类自己独立完成某些事情的能力。耦合指类与类之间的关系。使用变量遵循“就近原则”,局部位置有就使用,没有就去本类的成员位置查找,有就使用,没有就去父类的成员位置查找,有就使用,没有就报错。SEO靠我
super的用法和this很像
this代表本类对象的引用super代表当前对象的父类的内存空间标识
解释:可以理解为父类对象引用
用法
|功能|本类|父类|
|-|-|-|
|访问成员SEO靠我变量|this.成员变量名|super.成员变量名|
|访问构造方法|this(…)|super(…)|
|访问成员方法|this.成员方法名(参数值…)|super.成员方法名(参数值…)|子类中所有的构造方法默认都会访问父类的空参构造
问:为什么这样设计?
答:用于子类对象访问父类数据前,对父类数据进行初始化
即每一个构造方法的第一行都有一个:super()如果父类没有空参SEO靠我构造怎么办?
1)可以通过super(参数)的方式访问父类的带参构造
2)可以this(参数)的方式访问本类的其他构造
3)但是这样做比较麻烦,所以建议永远手动给出空参构造和带参构造。子类的空参构造访问父类SEO靠我的空参构造super();(可以省略不写,默认已有)。子类的带参构造访问父类的带参构造super(成员变量);所有的类都间接继承自Object类,Object类是所有类的父类
public class SEO靠我Father {public Father(int age){System.out.println("Father带参构造");}public Father(){System.out.println(SEO靠我"Father空参构造");} } public class Son extends Father {public Son(int age){super(age);SSEO靠我ystem.out.println("Son带参构造");}public Son(){System.out.println("Son空参构造");} } publicSEO靠我 class FatherTest {public static void main(String[] args) {Son s = new Son(10);Son s2 = new Son();} SEO靠我 }打印结果为:
Father带参构造
Son带参构造
Father空参构造
Son空参构造继承关系中,调用成员方法时,遵循“就近原则”,本类中有就直接使用,本类中SEO靠我没有就去父类查找。有就调用,没有就报错。
public class Father {public Father(){System.out.println("Father空参构造");}public FaSEO靠我ther(int age){System.out.println("Father带参构造");}public void show(){System.out.println("Father show")SEO靠我;} } public class Son extends Father{public Son(){System.out.println("Son空参构造");}puSEO靠我blic Son(int age){super(age);System.out.println("Son带参构造");}public void method(){System.out.println(SEO靠我"Son method");} } public class FamilyTest {public static void main(String[] args) {SEO靠我Son s = new Son();s.method();s.show();} }打印结果为:
Father空参构造
Son空参构造
Son method
Father show子类中SEO靠我出现和父类一模一样的方法时,称为方法重写,要求返回值的数据类型也必须一样
应用场景
当子类需要使用父类的功能,而功能主题又有自己独有需求的时候,就可以考虑重写父类中的方法了,这样既沿袭了父类的功能,又定义SEO靠我了子类特有的内容注意事项
子类重写父类方法时要用@overwrite注解来修饰父类中私有的方法不能被子类重写子类重写父类方法时,访问权限不能更低private < 默认 <protected < pubSEO靠我lic
public class Phone {public Phone(){}public Phone(String name){}public void call(String name){SystSEO靠我em.out.println("Calling "+name);} } public class NewPhone extends Phone{public NewPSEO靠我hone(){}public NewPhone(String name){super();}@Overridepublic void call(String name){super.call(nameSEO靠我);System.out.println("播放彩铃");} } public class PhoneTest {public static void main(StSEO靠我ring[] args) {Phone p = new Phone();NewPhone np = new NewPhone();p.call("Nick");np.call("Nick");} SEO靠我 }打印结果:
Calling Nick
Calling Nick
播放彩铃多态指的是同一个事物(或者对象)在不同时刻表现出来的不同状态。
前提条件
要有继承关系要有方法重写要有父类引用指向SEO靠我子类对象Person p = new Teacher();
成员变量:编译看左边,运行看左边
编译的时候看左边的数据类型有没有这个变量,有不报错,没有报错
运行的时候具体运行的SEO靠我是左边的数据类型里边的:此变量成员方法:编译看左边,运行看右边
编译的时候看左边的数据类型有没有这个方法,有不报错,没有报错
运行的时候具体运行的是左边的数据类型里边的:此方法原因:方法有重写,而变量没有SEO靠我。
public class Person{int age = 50;public void eat(){System.out.println("Eat.")} } pSEO靠我ublic class Student extends Person{//条件之一:要有继承int age = 20;@Override//条件之二:要有方法重写public void eat(){SSEO靠我ystem.out.println("Eat hamburgers.")} }好处:提高了程序的拓展性
坏处:父类引用不能访问子类的特有功能
处理方法:向下转型假SEO靠我设Student.class增加一个成员方法
public void study(){System.out.println("Study.") }那么主类需要这样写
public clasSEO靠我s PersonTest{public static void main(String[] args){Person p = new Student();//p.study() //会报错,因为p是PSEO靠我erson类的引用,没有study()成员方法Student s = (Student)p;/*向下转型,类似于强制类型转换强制类型转换:int a = (int)10.3;*/s.study();}SEO靠我 }向上转型:
Person p = new Student();
向下转型:
Student s = (Student)p;
bug:Person p = newSEO靠我 Student(); Student s = (Student)p;//正确 Teacher t = (Teacher)p;//报错实际SEO靠我开发中,方法的形参一般都是父类型,这样可以接受其任意子类对象,然后通过多态调用成员方法的规则调用指定子类对象的方法。
public class Animal {public void eat(){SysSEO靠我tem.out.println("eat");} } public class Cat extends Animal{@Overridepublic void eatSEO靠我(){System.out.println("cats eat fish");} } public class Dog extends Animal{@OverridSEO靠我epublic void eat(){System.out.println("dogs eat meat");} } public class AnimalTest SEO靠我{public static void main(String[] args) {Animal a1 = new Cat();Animal a2 = new Dog();show(a1);show(aSEO靠我2);}public static void show(Animal a){a.eat();} }cats eat fish
dogs eat meat格式
引用(对象) instanceof 数据类型
返回true或者false
作用
用来判断前边的引用(对象)是否是后边的数据类型
假设Cat类和Dog类分别增加成员方法:public void catchSEO靠我Mouse(){System.out.println("catch mouse") } public void guardHome(){System.out.prinSEO靠我tln("guard home") }主类show方法改变为:
public static void show(Animal a){a.eat();if(a instanceof CatSEO靠我){Cat c = (Cat) a;c.catchMouse();}else if(a instanceof Dog){Dog d = (Dog) a;d.guardHome();}}打印结果为:
caSEO靠我ts eat fish
catch mouse
Dogs eat meat
guard homefinal是一个关键字,表示最终的意思,可以修饰类,成员变量,成员方法
修饰的类:不能SEO靠我被继承,但是可以继承其他的类修饰的变量:是一个常量,只能被赋值一次修饰的方法:不能被子类重写final常见面试题
final修饰的变量是一个常量,那如果修饰的是基本类型或者引用类型的数据,有区别吗?
如果SEO靠我final修饰的是基本类型的常量,数值不能发生变化
如果final修饰的是引用类型的常量,地址值不能发生变化,但是该对象的属性值可以发生变化final, finally, finalize这三个关键字之SEO靠我间的区别是什么?
static是一个关键字,表示静态的意思,可以修饰成员变量和成员方法。
static 修饰成员变量表示该成员变量只在内存中存储一份,可以共享和修改。
随着类的加SEO靠我载而加载
优先于对象存在
被static修饰的内容,能被该类下所有的对象共享
这也是我们判断是否用静态关键字的条件
可以通过**类名.**的形式调用
示例
public class Student {StringSEO靠我 name;static String school; //static修饰成员变量public void show(){System.out.println("Name:"+name+" SchooSEO靠我l:"+school);} } public class Test {public static void main(String[] args) {Student SEO靠我s1 = new Student();Student s2 = new Student();s1.name = "Nick";Student.school = "HUST"; //通过“类名.”调用,SEO靠我所有对象共享s2.name = "Eva";s1.show();s2.show();} }Name:Nick School:HUST
Name:Eva School:HUST静态方法只能访问静态的成员变量和静态的成员方法(静态只能访问静态)在静态方法中没有this,super关键字
因为静态的内容是随着类的加载而加载,而this和super是随着对象的创建而存在
即先进SEO靠我内存的不能访问后进内存的回想前面我们的猫狗案例,提取出了一个动物类,这个时候我们可以通过Animal an = new Animal();来创建动物对象,但其实这是不对的。因为我说动物,你SEO靠我并不知道我说的是什么动物。只有看到了具体的动物,才知道是什么动物。所以说,动物本身不是一个具体的事物,而是一个抽象的事物。只有真正的猫、狗才是动物。同理,我们也可以对象,不同的动物吃的东西是不一样的,SEO靠我所以我们不应该在动物类中给出具体的体现,而是一个声明即可。
在Java中,一个没有方法体的方法定义为抽象方法(用abstract修饰),而类中如果有抽象方法,该类必须定义为抽象类(用abstract修饰SEO靠我)。
抽象类中可以有变量、常量、构造方法、抽象方法和非抽象方法(比普通类SEO靠我多了抽象方法)
思考:既然抽象类不能实例化,那要构造方法有什么用?
答:用于子类对象访问父类数据前,对父类数据进行初始化继续回到我们的猫狗案例,我们想狗的一般行为就是看门,猫的一般行为是捉老鼠。SEO靠我但是有些狗猫可以训练出钻火圈、跳高、做算术等行为。这些行为并不是狗猫天生就具备的。所以这些额外的行为定义到动物类中就不合适,也不合适定义到猫类或者狗类中,因为只有部分猫和部分狗具备。
所以,为了体现事物SEO靠我功能的拓展性,Java就提供了接口来定义这些额外行为,并不给出具体实现,将来哪些猫狗需要被训练,只需要这部分猫狗把这些额外行为实现即可。
成员区别
抽SEO靠我象类可以写变量、常量、构造方法、抽象方法、非抽象方法
接口可以写常量、抽象方法,JDK1.8引入了静态方法和默认方法关系区别 类与类:继承关系,只能单继承,不能多继承,可以多层继承类与接口:实现关系,可SEO靠我以单实现,可以多实现,可以在继承一个类的同时实现多个接口接口与接口:继承关系,可以单继承,可以多继承 设计理念的区别
抽象类:类中定义的是整个继承体系的共性内容
接口:定义的是整个继承体系的扩展内容包(package)就是文件夹,用来对类进行分类管理的,例如
学生的增加,删除,修改,查询老师的增加,删除,修改,查询其他类的增删改查基本的划分:按照模块和功能划分高级的划分package 包名1.包名2.包名3
package语句必须是程序的第一条可执行代码
package在一个程序中只能有一个PSEO靠我ackage必须放在java文件的第一行有效代码处,且一个.java文件只有一个package
import表示导包,可以写多个,必须写在package和class之间
class表示在定义类,写在impSEO靠我ort后,建议只写一个不同包下的类之间的访问,都需要加包的全路径。解决方法是导包。
28.5SEO靠我 格式import 包名;
import java.util.* 导入java.util包下所有类,这样效率低不推荐import java.util.Scanner 导入java.util.ScanneSEO靠我r类,推荐使用 28.6 注意事项 java.lang包下的类可以直接使用,无需导入,如果使用其他包下的类,则必须先导包用public修饰的类叫公共类,也叫顶级类。在一SEO靠我个.java文件中只能有一个顶级类,必须和文件名一致全类名=包名+类名 29 权限修饰符权限修饰符是用来修饰类、成员变量、构造方法、成员方法的,不同的权限修饰符对应的功能不同
publiSEO靠我cprotected默认private同一个类中√√√√同一个包中的子类或者其他类√√√不同包中的子类√√不同包中的其他类(无关类)√集合是用来存储多个同类型数据的容器,其长度可变。
长度固定SEO靠我用数组,长度可变用集合。集合分为Collection和Map。
集合的顶层都是接口。其中Collection是单列集合的顶层接口,Map接口是双列集合的顶层接口。学习思路:学顶层,用底层。
顶层SEO靠我:是整个继承体系的共性内容
底层:具体的体现和实现Collection:单列集合的顶层接口
List:有序,可重复
ArrayList:
LinkedList:
VectorSet:无序,唯一
HashSet:
TSEO靠我reeSetMap:双列集合的顶层接口
HashMap:
HashTable
TreeMap因为Collection是接口,不能用new关键字来创建。通过多态的方式创建其子类对象。
CSEO靠我ollection<String> list = new ArrayList<String>();, 等形式
概述:指某种特定的数据类型
作用:泛型一般是结合集合来一起使用的,用来限定集合中存储什么类型SEO靠我的数据
注意事项:1.前后泛型必须保持一致。2.后边的泛型可以不写,这是jdk1.7的新特性,叫菱形泛型。
例如List<String> list = new ArrayList<>(); SEO靠我 public class Demo01 {public static void main(String[] args) {Collection<String> list = new ArrayLiSEO靠我st<String>();//或者Collection<String> list = new ArrayList();list.add("Hello");list.add("World");SysteSEO靠我m.out.println(list);} }范型的小SEO靠我技巧:范型一般用字母E,T,K,V表示。E:Element;T:Type;Key Value
Iterator 是依赖集合存在,集合遍历的方式
public Iterator<E>SEO靠我 iterator()//根据集合对象,获取其对应的迭代器对象因为Iterrator是接口,所以在这里返回的是Iterator接口的子类对象。
迭代器是依赖于集合而存在的。
Iterator迭代器中的方法SEO靠我public boolean hasNext()//判断迭代器中是否有下个元素 public E next()//获取迭代器中的下一个元素 public staticSEO靠我 void main(String[] args) {Collection<String> coll = new ArrayList<>();coll.add("Hello");coll.add("WSEO靠我orld");Iterator<String> it = coll.iterator();while (it.hasNext()){System.out.println(it.next());}}打印SEO靠我结果
Hello World总结:
集合遍历的使用分为四大步三小步
1.创建集合对象
2.创建元素对象
3.把元素对象添加到集合对象中
4.遍历集合
1.根据集合对象获取其对应的爹太器
2.判断迭代器SEO靠我中是否有下一个
3.有则获取有序集合(俗称序列),该界面的用户可以精准控制列表中每个元素的插入位置,且用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。与CollectionSEO靠我集合不同,列表通常允许重复的元素。
简单记忆:有序,可重复,元素有索引增强for通过for循环+size()+get()的形式,遍历List集合
快捷键:itli列表迭代器指的是ListIterator接口,它是List集合特有的迭代器
该迭代器继承了Iterator迭代器,所以我们可以直接使用ListIterator<E> listIterator()SEO靠我 ListIterator<E> listIterator(int index)成员方法:
boolean hasPrevious(); E previous(); SEO靠我 int nextIndex(); int previousIndex(); List<String> list = new ArrayList<>(); SEO靠我 list.add("Hello"); list.add("World"); list.add("Java"); //通过ListIterSEO靠我ator正向遍历 ListIterator<String> it = list.listIterator(); while(it.hasNext()){ SEO靠我 String s = it.next(); System.out.println(s); } //逆向遍历 while(it.hasPSEO靠我revious()){ String s = it.previous(); System.out.println(s); }当使用普通迭代器SEO靠我(Iterator)遍历集合的同时,又往集合中添加了元素,就会报并发修改异常。
List<String> list = new ArrayList<>(); list.add("HellSEO靠我o"); list.add("World"); list.add("Java"); Iterator<String> it = list.iteratoSEO靠我r(); while(it.hasNext()){String s = it.next();if("World".equals(s)){it.add("JavaSE");//会报错并发SEO靠我修改异常} }产生原因:
迭代器是依赖于集合而存在,当判断成功后,集合中添加了新的元素,而迭代器不知道,所以报错了。(计数器会计算剩下的元素个数,所以add报错而remove不报错)本质SEO靠我是,迭代器遍历集合中的元素是,不能使用集合对象去修改集合中的元素。解决方案:
通过列表迭代器(ListIterator)解决 List<String> list = new ArrayLSEO靠我ist<>(); list.add("Hello"); list.add("World"); list.add("Java"); LisSEO靠我tIterator<String> it = list.listIterator(); while(it.hasNext()){String s = it.next();if("WorSEO靠我ld".equals(s)){it.add("JavaSE");} } 通过for循环+size()方法解决 List<String> list = SEO靠我new ArrayList<>(); list.add("Hello"); list.add("World"); list.add("Java"); SEO靠我 for(int i=0; i<list.size(); i++){if("World".equals(list.get(i))){list.add(i+1, "JavaSE");} SEO靠我 } for (int i = 0; i < list.size(); i++) {String s = list.get(i);System.out.println(s);SEO靠我 } 通过CopyOnWriteArrayList集合解决(它的底层已经解决了这个问题) CopyOnWriteArrayList<String> lSEO靠我ist = new CopyOnWriteArrayList<>(); list.add("Hello"); list.add("World"); liSEO靠我st.add("Java"); Iterator<String> it = list.iterator();//普通迭代器 while(it.hasNext()){ifSEO靠我("World".equals(it.next())){list.add("JavaSE");//并发} }面试题
什么是并发修改异常,怎么产生的,怎么解决
ConcurrentModifSEO靠我icationException增强for是JDK1.5的新特性,它是用来简化数组和Collection集合的遍历。
for(元素的数据类型 变量名:数组或Collection集合中的每一个元SEO靠我素) for(int a: array) for(Student l:list)注意事项:数组或Collection集合不能为null;增强for的底层是迭代器
for(SEO靠我String elem : list){ }数组:查询快,增删慢
链表:查询慢,增删快List集合是一个接口,它的常用子类有两SEO靠我个ArrayList和LinkedList
。
ArrayList的底层数据结构是数组,查询快,增删慢
LinkedList的底层数据结构是链表,查询慢,增删快
相同点:都是有序可重复的Set集合是Collection集合的子体系,它的元素特点是无序、唯一
Set集合是一个接口,所以不能通过new的方式直接创建对象Set集合中没有带索SEO靠我引的方法,不能通过普通for进行遍历Set集合的常用子类有两个HashSet集合和TreeSet集合。 Set<String> set = new HashSet<>();//实际使用SEO靠我不用Set<String>,直接用HashSet<String> set.add("Hello"); set.add("Java"); set.add(SEO靠我"Hello"); for(String s : set){System.out.println(s); }Java
Hello底层数据结构是哈希表对集SEO靠我合的迭代顺序不做保证没有带索引的方法不包含重复的元素
总结:无序,唯一,元素无索引。底层数据结构是哈希表 HashSet<String> set = new HashSet<>(); SEO靠我 set.add("Hello"); set.add("Java"); set.add("World"); for(String s : sSEO靠我et){//遍历法1:增强for循环System.out.println(s); } Iterator<String> it = set.iterator(); SEO靠我 while(it.hasNext()){//遍历法2:普通迭代器System.out.println(it.next()); }底层数据结构是哈SEO靠我希表+链表保证元素有序保证元素唯一
总结:有序,唯一。可变参数又称参数个数可变,它用作方法的形参出现,那么方法参数个数就是可变的了。
格式修饰符 返回值类型 方法名(数据类型... 变量名){} SEO靠我 可变参数的底层是一个数组如果一个方法有多个参数,将可变参数放在形参列表的最后。 public static void main(String[] args) {SysSEO靠我tem.out.println(getSum(1,2,3)); } public static int getSum(int... nums){return ArraySEO靠我s.stream(nums).sum();//可变参数的底层是数组 }特点:
键具有唯一性,值可以重复双列集合的数据结构只SEO靠我针对于键有效Set集合底层依赖的是Map集合
成员方法: public V put (K key, V value)网站备案号:浙ICP备17034767号-2