Java语言基础与面向对象编程实践
第一章 初识Java
1.1机器语言
机器语言是指一台计算机全部的指令集合。机器语言室友0和1组成的二进制数,是一串串由0和1组成的指令序列,可将这些指令序列交给计算机执行。
1.2汇编语言
负责把汇编语言翻译成二进制的机器语言,这种翻译程序就是汇编程序。
1.3高级语言
1954年第一个完全脱离机器硬件的高级语言FORTRAN诞生
1.3.1C语言
是一种计算机程序设计语言,它既有高级语言的特点,又具有汇编语言的特点。
1.3.2 C++语言
是具有面向对象特性的C语言,面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。通过面向对象的方式,将现实世界的事物抽象成类和对象,帮助我们实现对现实世界的抽象与建模。
1.3.3 C#语言
是一种面向对象的运行于.NET Framework之上的高级程序设计语言。C#与Java很相似(单一继承、接口、编译成中间代码在运行)
1.4 SQL语言
结构化查询语言(Structured Query Language,SQL)是一种数据库查询和编程的语言。用于存取数据库以及查询、更新和管理关系数据库系统
1.5 Java的诞生
·1995年Sun推出的Java只是一种语言
·JDK包括两个部分:运行环境(JRE)和开发环境(JDK)在运行环境包括了核心API、集成API、用户界面、发布技术、Java虚拟机(JVM)五个部分,而开发环境包括了编译Java程序的编译器javac.
·Java2的问世
JSE Java 2 Standard Edition(Java2标准版)
J2EE Java 2 Enterprise Edition (Java 2 企业版)
J2ME Java 2 Micro Edition(Java 2 微缩版)
1.6Java的特点
Java语言简单
Java语言是面向对象的
Java语言是分布的
Java语言是健壮的
Java语言是安全的
Java语言是平台无关性的
Java语言是可移植的
Java语言是高性能的
Java语言是多线程的
Java语言是动态的
1.6.1 就三个方面简单概述
Java语言是面向对象的
对象之间通过消息相互作用;任何对象都是某一类事物的实例。
面向对象编程语言则是以对象为中心,以消息为驱动(程序=对象+消息)
Java语言是平台无关的
用Java编写的应用程序,编译成字节码文件(.class),不用修改就可以在不同的平台上运行。
平台无关性有两种:源码代码级和目标源代码。Java语言是目标代码级的平台无关,只要在安装有Java虚拟机的平台上就可以运行,这就是所谓的“一处编译,处处运行”
1.7 Java程序的工作原理
1.7.1 Java虚拟机
java virtual machine 不是一台真实的机器,而是想象中的机器,通过模拟真实机器来运行Java程序。
Java虚拟机看起来同样有硬件,处理器、堆栈、寄存器,还具有相应的指令系统
Java字节码文件先后经过类装载器、字节码校验器解释器
类装载器:其主要功能是为执行程序寻找和装载所需要的类,就是把字节码文件装到 Java虚拟机中。
字节码校验器:对字节码文件进行校验,保证了代码的安全性。字节码校验器负责测试代码格式并进行规则检查,检查伪造指针、违反对象访问权限或试图改变对象类型的非法代码。
解释器:具体的平台并不认识字节码文件,最终起作用的还是这个最重要的解释器,它将字节码文件翻译成所在的平台能识别的东西。
1.7.2 垃圾回收机制
垃圾回收机制能自动释放内存空间,它是系统级的线程 System.gc() 这个方法通知Java虚拟机释放无用的资源,但Java虚拟机回选择在合适的时候释放无用的资源,具体的释放时间不是程序员
1.8 JDK 主要包含以下基本的工具
javac:编译器 将源程序转成字节码文件
java:执行器,运行编译后的字节码文件
javadoc:文档生成器,从源代码注释中自动产生Java文档
jar:打包工具,将相关的类文件打包成一个文件
java.lang:系统基础库
java.io:输入/输出库
第二章 数据类型和运算符
2.1 标识符和关键字
命名规则:
(1)标识符由字母、数字、下划线、美元符号组成,并且首字母不能是数字
(2)不能把Java关键字作为标识符
(3)标识符没有长度限制
(4)标识符对大小写敏感
·对于变量和方法名 要求第一个单词应以小写字母作为开头,后面的每个单词则都要以大写字母开头
·对于类名,它和变量名、方法名的区别在于,第一个单词首字母需要大写
·常量标识符应该都要使用大写字母,并且指出该常量完整的含义,如果是多个单词组成,则应该用下划线用来分割这些单词
·关键字不能作为变量名、方法名、类名和包名。
2.2 变量和常量
变量是一段有名字的连续存储空间(存储在计算机内存中),在Java代码中通过定义变量来申请并命名这样的存储空间,并通过变量的名字来使用这段存储空间。通过变量赋值可以改变变量的值,所以称为变量。变量是程序中数据的临时存放场所。
命名格式:变量类型 变量名 = 变量值; //int a = 1;int 类型为4个字节 32位
常量:利用final关键字来定义Java常量,其本质是不可变的变量,和变量不同的是,Java常量在程序中将无法进行赋值。
2.3 Java数据类型
分类两大类:基本数据类型(8种)和引用数据类型(3种)
基本数据类型{数值型(整数类型【byte、int、short、long】,浮点类型【float、double】)、字符型char、布尔型boolean};
引用数据类型{类class、接口interface、数组}
浮点型:需要在后面添加F符号 float a = 9.1F;
字符型:常用单引号括起来字符 Unicode编码占2个字节,一个汉字也是占2个字节
某些特殊字符可以采用转义符“\”来表示。\t 是制表符 \n代表换行符 \r 代表回车符。
2.4基本数据类型转换
·boolean类型不可以和其他数据类型转换。
·转换规则
容量小的类型自动转换成容量大的数据类型
大类型转换陈成小类型需要显示类型
容量大的数据类型转换成容量小的数据类型需要加上强制类型转换符,但可能造成精度降低或溢出
2.5 成员变量和局部变量
`根据变量的位置的不同可以将变量分为成员变量和局部变量
`成员变量在累的方法内部、方法外部定义的变量,其作用域从变量定义位置起到类结束;而局部变量是在方法内部定义的变量,其作用域从变量定义位置到方法结束。全局变量要在前面加static关键字,局部变量必须初始化参数。
2.6Java运算符
算术运算符:+ - * / ++ -- %
关系运算符:< > >= <= == !=
赋值运算符:= += -= *= /=
逻辑运算符:! && ||
位运算符:~ (按位非) & (按位与) | ^ >> << >>>(无符号右移)
在计算机中,所有信息都是以二进制形式存储的,可以对整数的二进制进行相关的操作
逻辑与运算规则:有一个运算数为假,其值为假,两个运算数为真,其值为真
第三章 流程控制
3.1 if语句语法
有三种形式
第一种
if(表达式){ //表达式必须是布尔类型 可以写成 a==3 但是不能写成a =3
代码块 //表达式的值为true则执行后面的代码块
}
第二种
if(表达式){
代码块A
}else{
代码块B
}
第三种
if(表达式1){
代码块A
}else if(表达式2){
代码块B
}else{
代码块C
}
嵌套if语句
if(表达式1){
if(表达式2){
代码块A
}else{
代码块B
}else{
代码块C
}
3.2 switch语句
switch(表达式){
case 常量1:
代码块A;
break;
case 常量2:
代码块B;
break;
default:
代码块X;
break;
}
switch中的表达式的值只允许是byte int short String char 类型
case后必须要跟一个与表达式类型对应的常量,case可以有多个,且顺序可以改变,但是每个case后面的常量值必须不同;break表示退出当前结构
3.3循环语句
(1)while循环
while(循环条件){
循环代码块
}
如果while循环的条件的值为true,则执行循环代码块,否则跳出循环,先判断后执行循环
(2)do while循环
do{
循环代码块
}while(循环条件);
当不满足循环条件就退出
这种循环的特点是至少会执行循环一次,先执行循环后判断
(3)for循环
for(表达式1;表达式2;表达式3){循环代码块}
for循环的特点是结构清晰、易于理解在解决能确定循环次数的情况下首先选择for循环
表达式1通常是赋值语句,一般是循环的初始部分,为循环参数赋初值,表达式可以省略,前提是在for前面定义过了
表达式2一般是循环条件,当满足条件就进入循环,不满足则退出也可以省略
表达式3也是赋值语句,属于循环结构的迭代部分,也可以省略
3.4 双重for循环
重点在于内循环的循环条件和外循环的循环参数有关
for循环用到了continue语句,continue的语句的主要作用就是为了跳出档次循环继续执行下一次循环
3.5跳转语句
在循环体内,break语句和continue语句的区别在于:使用break语句是跳出循环执行循环之后的语句,而continue语句是中止本次循环继续执行下一次循环。
第四章 方法与数组
4.1 方法
方法是为完成一定的功能,把程序中特定的代码组合在一起而构成的
方法在语法上功能主要有两个:
·结构化代码:将代码按照功能进行组织,使代码的结构比较清晰,容易阅读和修改,也就是程序的可维护性强。
·减少代码重复:一个固定的功能,可能会在程序中多次使用,在使用时只需要调用写好的方法,而不用重复书写对应的功能代码。
方法的书写时需要注意一下两点
①:逻辑严谨
方法实现的一个完整的功能,所以在书写时要考虑到各种可能的情况,并对每种情况做出恰当的处理。
②:通用性强(可重复利用)
方法实现的是一种功能,在实际实现时,可以根据需要,使方法具备一定的通用性, 除非必要,否则不要写专用的方法。在Java 语言中,恰当的使用方法,将使程序更加优雅,便于阅读和使用。
4.2方法只有四种类型:
有参有返
有参无返 void
无参有返
无参无返 void
Java 方法的格式:
[修饰符] 返回值类型 方法名([形参列表]){
方法体
}
大括号前面的内容称为方法头,大括号中的内容称为方法体
只要上述有一个不一样,那么这个参数列表就不一样!对于方法而言,即使同名也不是同一个方法,也就是下面讲的方法签名。
4.3方法里的属性
访问控制符:访问控制符限定方法的可见范围或者说是方法被调用,访问控制符有四种,按可见范 围从大到小分别是:public、protected、无访问控制符、private
形式参数:在方法调用时用于接收外界输入的数据
实参:调用方法时实际传给方法的数据
返回值:方法在执行完毕后返还给调用他的环境的数据,一个方法只能有一个返回值因此只能有一个返回类型;如果返回多个值,先转换为数组或一个对象
java中调用方法:对象名.方法名(实参列表)
4.4 方法的重载
概念
在同一个类中,允许存在一个以上的方法,只要他们的参数或类型或参数顺序不同即可
存在的原因
屏蔽了一个对象的同一类方法由于参数不同所在造成的差异
特点
与返回值类型无关,只看参数列表
例子
public void a(int a){}
public int a(){}
public void a(int a,String s){}
4.5 数组
数组是一种基本的数据存储结构,通俗的理解就是一组的集合,目的是用来一次存储多个数据。数据是程序中实现很多算法的基础,可以在一定程度上简化代码的书写;数组的好处:数组里的每个元素都有编号,编号从0开始,并且依次递增,方便操作这些元素;
使用Java数组:必须先声明数组,再给该数组分配内存;
数组对应在内存中一段连续空间。
数组元素必须是相同数据类型,也可以是引用数据类型,但是同一个数组中的元素必须是同一类数据类型。
4.6一维数组
·可以理解为一列多行、类型相同的数据,其中每个数据被称为数组元素;是引用数组数据类型
·使用数组时包括声明、创建、赋值、使用
·一维数组声明格式:
tyep varname[]; 或者 type[] varName(推荐)
·数组的长度一旦确定就不能改变也就数组是定长的,而且长度必须是整数
·java语言声明数组的时候不能指定其长度(元素的个数)
Eg:int a[5]; //非法
4.6.1初始化方式
·初始化
Java中的数组必须先初始化才能使用,所谓初始化就是为数组的数组元素分配内存,并为每个数组元素赋值。
·静态初始化(初始化时有我们自己指定每个数组元素的初始值,由系统决定需要的数组长度)
格式:数组名 = new 数组类型[]{元素1,元素2,元素3}
简化语法:数组名={元素1,元素2,元素3}
·动态初始化(初始化时有我们指定数组的长度,由系统为数组元素分配初始值)
格式:数组名 = new 数组类型[数组长度];
·初始化 = 定义数组+分配空间+赋值
·注意:不能静态和动态初始化同时使用:也就是说不能同时指定数组的长度和元素;
4.6.2数组的使用
数组的索引都是从0开始的,也就是说数组里的第一个元素的索引是0,第二个元素的索引是1....
给数组元素赋值 数组名[索引下标] = 数据类型的值
访问数组元素 数组类型 变量= 数组名[索引]
得到数组的长度 int len = 数组名.length;//length是数组的属性
遍历数组 数组元素的索引范围(0,长度-1)
4.6.3数组的经典例子(冒泡排序)
//冒泡排序
public class Demo {
public static void main(String[] args) {
int []age = {1,2,36,363,56,95,12,32,1232,3263};
for (int i = 0; i < age.length; i++) {
for (int j = i+1; j <= age.length-1; j++) {
if(age[i] > age[j]){
int temp = age[i];
age[i] = age[j];
age[j] = temp;
}
}
}
System.out.println(Arrays.toString(age));
}
}
//输出为:[1, 2, 12, 32, 36, 56, 95, 363, 1232, 3263]
4.6.4分配内存空间
分配内存空间
数组名 = new 数据类型[数组长度]
new关键字用来实现为数组或对象分配内存
数组具有固定长度获取数组的长度:数组名.length
定义数组+分配内存
数据类型[] 数组名 = new 数据类型[数组长度];
定义数组时不指定长度,分配空间时指定长度.例如:String cities[] = new String[6]
数组元素
数组名[下标值]
数组下标从开始 scores[0]=75;
数组的内存分配
堆内存和栈内存
如定义一个数组int[] score = new int[5]; 将在栈内存中卫scores分配内存空间,其值是一个不确定的值当执行语句scores = new int[5]时,将在堆内存中分配连续5个空间,每个空间4个字节,用于存放整形数据,其初始值为0,然后将短空收地址,也就是第一个元素的地址,当执行四个赋值语句时,分别用指定值填充到对应元素位置。如果此时将null值赋给scores时,scores变量将不再指向任何位置,此时堆内存中分配的空间就变成了垃圾,由垃圾回收器在某一时间进行回收。
4.6.5二维数组
二维数组:其实是一个一维数组,他的每个元素又是一个一维数组,可以看作是一张表格
初始化:
动态初始化 int[][] arr = new int[3][2];//定义了一个二位数组,其中有3个一维数组,每一个一维数组中有两个元素
静态初始化
int[][] arr = {{1,2},{3,4},{5,6}};
int[][] arr = new int{{1,2},{3,4},{5,6}}
4.7 操作数组的工具类Arrays
static int binarySearch(type[] a,type key) 使用二分法搜索法来搜索key元素在数组中的索引;若a数组不包括key,返回负数。(该方法必须已按升序排列后调用)
static int binarySearch(type[] a,int formIndex,int toIndex,type key) 使用二分法来搜索key元素在数组中从formIndex到toIndex的索引;若a数组不包括key,返回负数。(该方法必须已按升序排列后调用)。
static boolean[] copyOf(type[] original,int newLength) 复制指定的数组
static byte[] copyOfRange(type[] original,int from,int to) 将数组的制定范围复制到一个新的数组
static void sort(type[] a) //对指定的数组按数字进行升序
static String toString(type[] a) 返回指定数组内容的字符串表示形式。多个数组元素之间用英文逗号或空格隔开。
增强for循环
foreach
for(参数类型 参数名: 数组名){
}
4.8 方法的递归调用
递归调用是指一个方法在他的方法体内调用他自身,在递归调用中
第五章 String字符串
5.1 String类
String 类表示字符串,Java 程序中的所有字符串都做为此类的对象。Strin不是基本数据类型,他是一个类。因此对象的初始值都是null,它是一种特殊的对象。String字符串是常量,创建之后就不能修改了。String是最终类,不能被继承。这里说的不可变是指在堆内存中创建出来的String字符串不可变。
5.2 String类常用的方法
(1)连接字符串
如果在实现的过程中需要在某个字符串后面添加一个字符串可以使用concat(String str)方法
例 String str = "aaa";
String str2 = str.concat("bbbb");
System.out.println(str);//aaa 因为str是常量
System.out.prinln(str2);//aaabbbb
(2)比较字符串
比较字符串常用的两个方法是运算符“==” 和String类的equals方法。
使用“==” 比较两个字符串,是比较两个对象的地址是否一致,本质上就是判断两个变量是否只指向同一个对象。而String类的equals方法则是比较两个String字符串的内容是否一致,返回值是一个布尔类型。
(3)从字符串中返回索引处的字符串值(从0开始)
public char charAt(int index)
(4)返回字符串的长度。
public int length();//这个方法是在找出字符创长度用的
例:String str = "abcd";
System.out.prin(str.length());//输出4
public int length;//这个是在求出数组长度用的 通过数组名.length 获取
例: String[] arr = {"s","d","f"};
System.out.println(arr.length);//输出3
(5)返回字符串第一次出现处的索引
public int indexOf(String str)
(6)替换字符串
public String replace (char oldChar,char newChar)
返回来的值必须重新接收不然就是旧的
(7)判断字符串是否可以指定的前缀开始
public boolean startsWith(String str)
(8)判断字符串是否可以指定的前缀结束
public boolean endsWith(String str)
(9)将此字符串中所有的字符都转换为大写
public String toUpperCase()
(10)将此字符串中所有的字符都转换为小写
public String toLowerCase()
(11)字符串的截取
public String substring(int beginIndex,int endIndex);//下标数字与数组的下标是一样的
例 String str = "abcdefghijklmn";
String newStr = str.substring(0, 3);
System.out.println(newStr);//输出abc
注意:包括开始下标的字符但是不包括末尾下标的字符
(12)返回字符串的副本,忽略原来字符串前后的空格 但是不包括中间的空格
public String trim()
例:String s = " 52 .doc ";
System.out.println(s.trim());//输出 52 .doc
(13)返回基本数据类型参数的字符串形式
public static valueOf(基本数据类型参数)
注意:静态方法是通过 类名.方法名
(14)指定分隔符分割字符串返回分隔后的字符串数组
public String[] split(String regex)
例子 String sp = "a|s|dd|d";
String[] nSp = sp.split("\\|");//这里不能用 / 符号来分割 不然是显示 |
System.out.println(nSp[1]); //输出s
5.3 StringBuffer类
StringBuffer类也可以存放字符串。与String类不同的是,StringBuffer字符串代表的是可变的序列,可以对字符串对象的内容进行修改。
StringBuffer(): 构造一个不带字符的字符串缓冲区,其初始容量为16个字符
StringBuffer(String str) 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
StringBuffer字符串使用场合为经常需要对字符串内容进行修改的操作场合
5.4 StringBuffer 类的使用
格式定义:
StringBuffer sb = new StringBuffer();//初始化 底层创建了长度为16的数组
StringBuffer sb = new StringBuffer("qqq");// 底层创建了长度为16+3的数组
5.5 StringBuffer 常用方法的使用
(1)将指定的字符串追加到字符序列中
public StringBuffer append(String str)
(2)将指定的StringBuffer追加到字符序列中
public StringBuffer append(StringBuffer str)
(3)将字符数组参数的形式追加到序列中
public StringBuffer append(char[] c)
(4)将字符数组参数的子数组的字符串表示形式追加到次序列中,从索引offset开始,此字符序列的长度将增加len
public StringBuffer append(char[], int offset,int len)
(5)将字符串插入到次序列中,offset表示插入的位置
public StringBuffer insert(int offset,String str)
第六章 类和对象
6.1 类和对象的概述
面向对象的三大特征:封装、继承、多态
对象具有的行为称为方法;类是对具有相同属性和相同行为的对象的抽象 类的关键字是class
对象有自己的属性和方法,而类是具有相同特征的一类对象的集合,比如人类、动物类 而小明这个叫对象
对象创建的过程: 声明对象、创建对象、给对象赋值、使用
对象赋值步骤:对象名.属性; 对象名.方法
6.2 封装
封装就是将抽象的到的属性和行为结合起来,形成一个有机整体,也就是类。类里面的属性和一些方法需要去隐藏起来,不希望直接对外开放,但同时提供外部访问的方法来访问这些需要隐藏的属性和方法
所谓良好的封装就是对属性使用private修饰 对方法使用public来提供外界类来交换数据
6.3 构造方法
public class Student{
private String name;
private int age;
private int sex;
private int grade;
//构造方法,用户初始化对象的成员变量
public Student(String name,int age,int sex,int grade){
this.name = name;
this.age = age;
this.sex = sex;
this.grader = grade;
}
//省略Students类中的其他方法
}
6.4 对象初始化过程
初始代码块
{
代码块
}
·创建对象时默认初始化成员变量
·定义类时,给成员变量赋初值
·调用构造方法时使用构造方法所带的参数初始化
6.5 重载的定义
在同一类中,可以有两个或两个以上的方法具有相同的方法名,但他们的参数列表不同。在这种情况下,该方法就是重载。
参数列表的三种情形:参数的数量不同、参数的类型不同、参数的顺序不同
必须注意的是仅返回值不同的方法不叫重载方法。其实重载方法之间并没有任何联系这是碰巧名字相同而已,返回值是运行时才知道的。
例:
pubic Student(String name,int sex){
this.name = name;
....
}
pubic Student(String name,int age,int sex){
this.name = name;
....
}
//无参构造方法
public Student(){
}
第七章 包和访问控制
7.1 Java包
为了更好的组织类,Java提供包机制。包是类的容器,用于分隔类名空间。如果没有指定包名,所有的类都属于一个默认的无名包
包的使用:在第一行写上,package com.lanqiao.demo;
导入包的语法形式:import 包名.类名;
7.2 Java 包的作用
(1)提供了类似于操作系统树形文件夹的组织形式,能分门别类地存储、管理类、易于查找并使用类
(2)解决了同名类的类命名冲突。
(3)包允许在更广的范围内保护类、属性、方法
JDK提供的类库中的包主要功能:
java.lang: 提供利用Java变成语言进行程序开发的基础类,例如String、math、Integer、System和Thread
java.util:Java工具类,包含对集合的操作、事件的模型、日期时间设置
java.io:通过数据流、序列化和文件系统提供系统输入和输出
java.awt:包含用于创建用户界面和绘制图形图象的类
7.2 访问权限
7.2.1对类的访问控制
Java语言中的访问权限修饰符有4种,但却有只有三个关键字,分别是private、public、protected。因为不写访问修饰符的时候会有个默认修饰符
对于类而言,能使用的访问修饰符只有public和default。如果使用public修饰,则表示该类在人任何地方都能被访问,如果不写访问修饰符权限,则该类只能在本包使用
7.2.2 对类成员的访问控制
1.private私有权限,可以修饰方法、属性、构造方法、普通方法,只能在定义他们的类中使用
2.default默认权限,可以不写关键字但是,只能在定义他们的类以及同包的类中使用
3.protected受保护权限 如果有不同包中的类想调用它们,那么这个类必须是这些成员所属类的子类。
4.public公共权限 是权限最大的访问权限修符
7.3 访问修饰符总结
修饰符 | 类内部 | 同一个包中 |
private | Yes | |
default | Yes | Yes |
protected | Yes | Yes |
public | Yes | Yes |
7.4 static 关键字
在类成员的声明前,加上static关键字就能创建出这样的静态类成员。static成员最常见的例子是main方法。因为程序开始执行时必须调用main方法,所以声明为static方法
声明为static的变量称为静态变量或类变量。可以直接通过类名引用静态变量。静态变量与类相关联,类的所有实例共同拥有一个静态变量。
7.5 static关键字的作用
7.5.1 用static修饰类的成员变量
用static修饰的类的成员变量是静态变量,对该类的所有实例来说,只有一个静态值存在。所有实例公用一个变量。静态变量是指不管类实例出多少个对象,系统仅在第一次调用累的时候为静态变量分配内存
例 public class Student{
Student wangYun = new Student();
wangYun.avgAge = 22;
System.out.println("王允所在的班级的平均年龄是"+wangYun.avgAge);//输出22
Student liuJT = new Student();
liuJT.avgAge = 21;
System.out.println("王允所在的班级的平均年龄是"+wangYun.avgAge);//输出21
System.out.println("刘静涛所在的班级的平均年龄是"+liuJT.avgAge);//输出21
}
class Student{
private static int avgAge;//类变量,存放平均年龄
}
静态方法只能访问静态成员
非静态方法既可以访问静态成员又可以访问非晶态成员
7.5.2 用static修饰类的成员方法
修饰方法的时候,该方法绑定于类本身
都是通过:“类名.静态变量名”和“类名.静态方法”
静态变量不能操作实例变量
7.6 Java静态块
在使用new关键字创建并初始化对象的过程中,具体的初始化分为下面四步
(1)给对象的实例变量分配内存,默认初始化成员变量
(2)成员变量声明时的初始化
(3)初始化块初始化
(4)构造方法初始化
静态块语法:
static{
代码块
}
Java类首次载入JVM时,会对静态变量(含静态块)或方法进行一次初始化,方法不被调用时不会执行的,就是说静态变量和静态块是在类首次载入JVM时被执行。
静态变量和静态块都是在类实例化对象前被执行
执行顺序
static{代码块}
{ 代码块}
有参构造方法 public Student(String name,int age){this.name = name; this.age = age}
静态块在第一个对象创建时运行
初始化块在每个对象创建时运行
区别是静态块只执行一次,操作的内存在静态区
初始化块每个对象构造时都需要执行一次,操作的内存在用户区
7.6.1 类变量和实例变量的区别
类变量指的是静态静态变量,也就是在变量前加static关键字
实例变量也叫对象变量
类变量和实例变量的区别在于:类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象
第八章 继承和多态
8.1 抽象和封装
面向对象首先要做的就是抽象。首先要先进行类抽象,就是发现类并定义类的属性和方法
类抽象的目的在于抽象出类,并确定属性和方法,而接下来的封装,则要在封装的角度隐藏类的属性,提供公有的方法来访问这些属性。
8.2 继承的概念
语法:
class A extends B{ 定义部分 }
A类继承B,B称为父类、超类或基类,A类称为子类、衍生类或导出类
在子类的构造方法中有super(name);表示调用父类的有参构造方法;在同一个类中,this关键字代表这个类对象本身。
8.3 继承和访问权限
继承最大的好处就是,子类可以从父类中访问权限修饰符为public和protected的属性和方法,但是不能访问private的方法;
子类可以继承父类中用默认访问权限修饰符的属性和方法,但子类和父类必须是在同一个包中。
子类无法继承父类的构造方法;但是可以通过getter和setter方法访问属性
8.4 方法重写
如果父类中的方法不能满足子类的需要,则可以在子类中对父类的同名方法进行覆盖,这就是重写。
重写满足的条件:
重写方法与被重写方法同名,参数列表也必须相同。
重写方法的返回值类型必须和被重写方法的返回值类型相同或是其子类。
重写方法不能缩小被重写的方法的访问权限
注意:用final修饰的变量即为常量,只能赋值一次,如果用final修饰方法,则该方法不能被子类重写。用final修饰类,则这个类不能被继承。
8.5 属性覆盖
第一种情况:
public class Sub extends Super{
public int i = 100;
public static void main(String[] args){
Sub sub = new Sub();//创建子类对象
System.out.print(sub.i);//输出100
}
}
class Super{
public int i = 50;
}
程序运行结果是100,说明子类的属性(值为100)覆盖了弗雷德属性(值为50).
第二种情况:
public class Sub extends Super{
public int i = 100;
public static void main(String[] args){
Super sub = new Sub(); //创建父类对象,用子类实现
System.out.print(sub.i); //输出50
}
}
class Super{
public int i = 50;
}
程序运行结果是50 说明创建父类对象实现的时候用子类实现,此时这个对象的属性为父类属性,不被子类覆盖
第三种情况
public class Sub extends Super{
public int i = 100;
public void show(){
System.out.prin("子类方法");
}
public static void main(String[] args){
Super sub = new Sub(); //创建父类对象,用子类实现
sub.show(); //调用的是子类方法,覆盖了父类方法
System.out.print(sub.i); //输出50
}
}
class Super{
public int i = 50;
public void show(){
System.out.print("父类方法");
}
}
程序输出为“子类方法”和50 ; 说明,父类的方法被子类覆盖,调用了子类重写的方法,显示出“子类方法”
8.6 多态
8.6.1 向上转型
满足的三个条件:
1.必须存在继承
2.必须存在重写
3.父类引用指向子类对象(向上转型)
向上转型的好处:
不需要针对父类的多个子类写多个方法减少代码编写量,而且增加了程序的扩展性;有局限性就是只能调用父类的方法不能调用父类子类特有的方法。
8.6.2 向下转型
是父类的引用指向子类对象。在这个过程中需要类型转换。Java提供了instance of 运算符 不是方法,可以进行类型判断,避免抛出异常。 格式: 对象 instance of 类 //该运算符是判断某一个对象是否属于某一个类,得到具体的类型在具体强转
多态的两种形式就是chong
第九章 抽象类和接口
9.1 抽象类
·在面向对象是世界里,所有的对象都是通过类来实例化的,但并不是所有的类都直接用来实例化对象。如果一个类中没有包含足够的信息来描绘一个具体的事物,这样的类可以形成抽象类;抽象的概念就是看上去不同但是实际是有相同概念的具体对象
·提供一种专门供子类来继承的类 这个类就是抽象类 语法: abstract class 类名{ }
·Java还提供了一种特殊的方法,这个方法不是完整的方法,只含有方法的声明,没有方法体,格式:其他修饰符 abstract 返回值 方法名()
9.2 抽象类特征
(1)抽象类不能被直接实例化 也就是不能被new出来
(2)抽象类的子类必须实现抽象方法,除非子类也是抽象类
(3)抽象类里可以有普通方法,也可以有抽象方法,但是有抽象方法的类必须是抽象类
(4)抽象类里可以没有抽象方法
9.3 接口的定义及其特征
·如果抽象类中的方法都是抽象方法,那么由这些抽象方法组成的特殊的抽象类就是所说的接口;接口是一种特殊的抽象类
·接口是一系列方法的声明,使一些抽象方法的集合。
·抽象类更侧重对相似的类进行抽象,形成抽象的父类以供子类继承使用,而接口往往在设计的时候是定义模块与模块之间的规约或者标准,比如蓝牙。
·一个接口可以继承多个父接口
接口是先继承在实现
接口的格式:
修饰符 interface 接口名 extends 接口列表{接口体} //修饰符可有可无 没有的时候只限于同包的类和接口
9.4 接口的特征
接口不允许有实体方法
接口中可以有成员变量,默认修饰符是public static final接口中的抽象方法必须用public修饰
一个类可以实现多个接口
接口可以继承其他接口,实现接口合并的功能
第十章 排序算法
10.1冒泡排序
就是依次比较相邻的两个数,将小数放在前面,大数放在后面。
排序口诀:
n个数来比较,外层循环n-1 内层循环 n-i-1
外层循环控制轮次,内层循环控制次数
10.1.2 经典例子
//冒泡排序
public class Demo {
public static void main(String[] args) {
int []age = {1,2,36,363,56,95,12,32,1232,3263};
for (int i = 0; i < age.length; i++) {
for (int j = i+1; j <= age.length-1; j++) {
if(age[i] > age[j]){
int temp = age[i];
age[i] = age[j];
age[j] = temp;
}
}
}
System.out.println(Arrays.toString(age));
}
}
//输出为:[1, 2, 12, 32, 36, 56, 95, 363, 1232, 3263]
10.2 插入排序
插入排序包括直接插入排序、二分插入排序、链表插入排序和希尔排序