复习
一.多态
面向对象的特征。
理解:一个对象可以使用不同类型的引用变量来表示
不同类型的引用变量:父类型 或 本类型
表现:一个父类型引用指向子类对象。
好处:提高了代码的扩展性
弊端:只能访问子父类共有的成员。
前提:必须有继承或实现接口
转型:
基本类型: 自动转换 和 强制转换
引用类型: 向上转型 和 向下转型
向上转型 : 父类型引用指向子类对象
向下转型 : 将父类型引用强转为子类类型引用
注意:
1.转换的过程中,对象没有变,一直都是子类对象,改变的是引用类型,一会是父类型一会是子类型。
2.转型的过程中容易转成不合法的类型,出现类型转换异常,ClassCastException
instanceof:
关键字、比较运算符,结果是boolean
作用:左边引用变量所指向的对象是否是右边的类型
a instanceof Dog
注意: instanceof 判断类型时,如果类型有父子关系,必须先判断子后判断父,如果是兄弟关系没有顺序要求。
例子:
方法参数 多态数组
二.抽象类
1.abstract关键字,抽象的意思,修饰符,修饰类或方法
2.修饰类:抽象类,不能创建对象,类中的成员可以是:成员变量、方法,构造方法,抽象方法
3.修饰方法:抽象方法,需要在抽象类中或接口中
抽象类通常是作为父类存在,子类继承父类后,要将父类中的抽象方法全部重写后,子类才可以创建对象,否则子类还是抽象类。
三.接口
1.作用:定义方法的声明(规则),谁需要这些规则谁就实现该接口,并实现接口中的方法。
2.修饰符 interface 接口名{
常量
抽象方法
}
也是类,是一个特殊的类
接口中的成员都是有固定修饰符的,并且都是公共成员。
3.接口也是不能创建对象,需要有实现类(子类)实现implements(继承)接口
实现类需将接口中的所有抽象方法全部实现,才可以创建对象,否则还是抽象类
4.类和类: 单继承
类和接口: 多实现
接口和接口:多继承
注意:接口中没有构造方法
class 子类 extends 父类 implements 接口A,接口B,…{}
子类 子 = new 子类(); 全部
父类 子 = new 子类();
A 子 = new 子类();
B 子 = new 子类();
class 子类 extends 父类{}
class 父类 implements A, B{}
课程
一. 电脑USB综合案例
定义笔记本类,具备开机,关机和使用USB设备的功能。
笔记本类:包含运行功能、关机功能、使用USB设备功能
USB接口:包含开启功能、关闭功能
鼠标类:要符合USB接口【实现USB】
键盘类:要符合USB接口【实现USB】
public class Demo1 {
public static void main(String[] args) {
Computer c = new Computer();
c.useMouse(new Mouse());
c.useKeyboard(new Keyboard());
}
}
class Computer{
void useMouse(Mouse m){
m.work();
}
void useKeyboard(Keyboard kb){
kb.work();
}
}
class Mouse{
void work(){
System.out.println("鼠标工作");
}
}
class Keyboard{
void work(){
System.out.println("键盘工作");
}
}
分析:
- 定义出一个MacBox 笔记本类, 需要设计出 开机方法openBox, 关机方法 closeBox,
方法useUSB(可以使用USB设备) - 定义出USB接口, 功能就是如何使用USB, 两个方法(抽象方法), openUSB, closeUSB
- 定义出一个Mouse类, 实现USB接口, 因为鼠标需要符合USB的设计规范, 才能正常使用USB, 重写USB中的两个方法功能openUSB, closeUSB
- 定义出一个KeyBoard类, 实现USB接口, 因为键盘需要符合USB的设计规范, 才能正常使用USB, 重写USB中的两个方法功能openUSB, closeUSB
- 定义出一个测试类, 测试鼠标和键盘的使用过程
public class Demo2 {
public static void main(String[] args) {
Computer1 computer = new Computer1();
computer.useUSB(new Mouse1());
computer.useUSB(new Keyboard1());
}
}
interface USB{
void work();
}
class Computer1 {
void useUSB(USB usb){ //多态
usb.work();
}
}
class Mouse1 implements USB{
@Override
public void work() {
System.out.println("鼠标工作");
}
}
class Keyboard1 implements USB{
@Override
public void work() {
System.out.println("键盘工作");
}
}
二. 匿名内部类
1、没有名字的内部类
2、匿名内部类的使用前提:
匿名类:继承一个类
匿名类:实现一个接口
3、格式:
new 父类类名或者接口名() {
父类方法的重写或者是接口内容的实现
}
4、本质:
(1) 创建了一个类的子类对象、接口的实现类对象
(2) 更强调关系的一种写法
5、内部类的名称总结:
(1) 如果是有名字的内部类,类名【外部类名$内部类名】
(2) 如果是没有名字的内部类,通过匿名内部类的顺序描述类名,第一个匿名内部类的名称【外部类名$1】,第二个匿名内部类类名【外部类名$2】
public class Demo3 {
public static void main(String[] args) {
new Outer().function();
}
}
/*
* 匿名内部类:
* 指的就是没有类名的类
* 前提:必须有继承或实现
* 实际:创建匿名的子类对象,也就是创建子类对象的一种简写格式。
* 格式:
* new 父类名/接口名(){
* 方法
* };
* 建议:父接口或父类中的方法不要太多,通常是1-2个。
* */
abstract class ABC{
abstract void method();
}
class Outer {
/* class Inner extends ABC{
@Override
void method(){
System.out.println("method");
}
void show(){}
}*/
public void function(){
//1.继承类 2,重写方法 3.创建对象 4.调用方法
/*Inner inner = new Inner();
inner.method();*/
/*new ABC(){
@Override
void method(){
System.out.println("method");
}
}.method();*/
ABC abc = new ABC(){ //多态,父类引用指向子类对象
@Override
void method(){
System.out.println("method");
}
};
abc.method();
//abc.show(); //编译报错
new ABC(){
@Override
void method(){
System.out.println("method");
}
//子类特有方法 --可以有,但是实际中不建议写
void show(){
System.out.println("show");
}
}.show();//匿名内部类相当于创建了对象,所以直接调用才会显示
}
}
三. API的使用方式
概述: java的源代码编译之后,形成.class的字节码文件,包含了这个类中的所有内容,因此如果想在脱离源代码的前提下使用.class字节码文件,可以打包生成jar包(在Java中.class字节码文件的标准压缩包就是jar包).
(一) 使用IDEA导出jar包
- File->Project Structure
或者: 快捷键:ctrl + alt + shift + s
-
选择 Artifacts -> JAR -> From modules …
点一下图中的加号+, 才会出现JAR系列选项
-
弹出如下消息框
-
点击上图ok后,回到如下图所示界面:
- 点击ok前, 先选择apply(应用), 然后点击ok
-
点击ArrayUtils.jar下的Build.
-
显示下图,表示已经导出完毕.
这种导出方法,导出的是该项目中的所有.class文件
(二) IDEA导入jar包
- 在项目上右键,创建文件夹,并取名为lib,名称可以任意.
- 将要导入的jar包复制到该文件夹中.
-
打开File—Project Structure,选择Modules,选择要进行添加jar包的项目,点击右侧
Dependencies,点击下图所示加号.
-
选择如图所示:JARs or directories…
-
选择刚才复制的jar包的位置,点击ok.添加完毕.
(三) 删除jar包
仍然选择File—>Project Structure—>Modules,选中jar包,选择减号,移除.再删除lib下的jar包即可.
(四) API的来源和使用流程
-
概念:
API(Application Programming Interface,应用程序接口)是一些预先定义的接口
(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定.
用途:
用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节 -
使用流程: 双击打开API
点击显示,点击索引,在输入框中输入类名.会根据类名的索引进行显示和筛选.双击需要查找的类,右侧会显示该类的详细说明.
-
右侧类的详细说明如下:
-
查看构造方法,判断是否可以创建对象
-
查看每个方法的返回值类型,判断是否是自己需要的方法
-
查看每个方法是否静态,判断是否可以使用类名直接调用
-
查看方法名称
-
查看方法的详细解释和参数列表
(五) 文档注释
-
文档注释: 以注解的形式描述类或者方法的功能和基本信息, 写在类和方法的声明之上
/**
以注解方式描述类或方法的功能
*/ -
常见API注解:
作者:@author lyl
版本:@version v1.0
从哪个版本该是:@since
参数:@param 参数名称 参数名称的解释
返回值:@return 返回内容的解释
/**
* 该类是用来演示文档注释的编写。
* @author zs
* @since jdk1.0
* @version v1.0
*/
public class Demo4 {
/**
* 该方法使用来获取数组中最大元素
* @param arr 要操作的数组
* @return 返回数组的最大元素
*/
public int getMax(int[] arr){
return 0;
}
}
四. Object类
(一) 概述
-
Object是类层次结构的根类.每个类都使用Object作为超类.所有对象(包括数组)都实现
这个类的方法.随意定义一个类型,不手动显式定义其父类,那么这个类的父类就是Object类. -
构造方法:
Object() : 空参构造中,第一行, 没有调用super(), 因为Object没有父类
用途:
(1) 创建Object类的对象的方法.
(2) 子类访问,所有子类都会直接或者间接的访问到这个顶层父类的构造方法.
(二) toString方法
- public String toString()
返回当前对象的字符串表示.默认Object类的toString方法,由
getClass().getName() + ‘@’ + Integer.toHexString(hashCode())这几部分组成.
(1) getClass().getName() 表示类的完全限定名.
(2) hashCode() 表示根据内存地址通过哈希算法生成的哈希码值.
(3) Integer.toHexString() 表示无符号十六进制的字符串表示形式.
2.对象返回这样一个地址值的字符串,没有什么意义,因此对于子类而言,需要重写父类的这个方法.
3.重写的原则:返回该对象中的所有成员变量的值(对象的属性)
4.快捷键生成:alt + insert -> 点击 toString方法
5.使用打印语句打印一个对象,其实打印的就是这个对象的toString()方法结果.
(三) equals方法
1.public boolean equals(Object obj)
指示其他某个对象是否与此对象"相等".
2.对于任何非空引用值x和y,当且仅当x和y引用同一个对象时,此方法才返回true(x ==
y 具有值true).也就是在Object类型中,比较的是两个引用是否指向了同一个对象.如果
是,才返回true.相当于是在比较两个对象的地址值是否相同.
3.实际生活中,比较两个对象的内存地址,没有什么意义.因此在自定义的子类中,都要重
写这个方法.
4.重写原则:一般比较两个对象中的所有属性,是否全部相同.
5.快捷键生成:alt + insert -> 点击 equals() and hashCode()方法.
6.==和equals方法的区别:
1)比较内容的不同:
==可以比较任意数据类型,既可以比较基本数据类型,也可以比较引用数据类型.
equals方法只能比较引用数据类型.
2)比较规则不同:
==在比较基本类型的时候,比较的是数据的值,比较引用类型时,比较的是地址值.
equals方法在重写之前,比较的是两个对象的地址值,在重写之后,比较的属性值.
public class Demo5 {
public static void main(String[] args) {
Person p = new Person(10);
Person p1 = new Person(12);
Person p2 = p;
System.out.println(p.equals(p1));
System.out.println(p.equals(p2)); //equals方法重写,比较年龄是否相等
System.out.println(p == p1);
System.out.println(p == p2); //比较的引用的指向,指向的是否是同一对象
System.out.println(Integer.toHexString(p.hashCode()));
System.out.println(p1.hashCode()); //返回哈希值
System.out.println(p);
System.out.println(p.toString());
}
}
/*
* Object类:
* 是java的根类,是所有对象的直接或间接的父类,包括数组都继承了该类中的方法。
* 构造方法:
* Object()
* 方法:
* String toString(): 返回的是对象的字符串描述,描述是固定格式的:类名+@+哈希值
* 该方法可以手动调用也可以不用手动调用,默认输出对象名,自动调用该方法
* 返回的字符串信息看不懂,通常这个方法也重写,显示属性信息
* int hashCode(): 返回对象的哈希码值
* 默认情况下,不同对象哈希值不相同。
* 如果将该方法重写,可能出现不同对象有相同的哈希值。
* 该方法的值是否相同不能决定是否是同一对象,判断是否是同一对象方案一 == 比较,方案二 Object类中的equals方法比较
* boolean equals(): 调用者和参数进行比较,比较对象是否相等,实际比较的是两个引用地址值是否相同
* 底层原理是:this == 参数,与直接使用 == 是一个意思。
* 通常该方法会进行重写,建立有意义的比较,比较的是属性。
* == 和 equals方法区别:
* 1.== :
* 基本类型:数值 引用类型:比较引用指向
* 2.equals:
* 默认比较引用指向,通常重写,比较类中的属性值是否相同
*
* javabean类:
* 1.属性私有化
* 2.无参数构造方法
* 3.set和get方法
* 4.该类是公共类
*
* 5.有参数构造和返回属性信息方法(toString()) 可选
* 6.equals和hashCode 可选
*
* */
class Person{
private int age;
public Person(){
super();
}
public Person(int age){
super();
this.age = age;
}
/*@Override
public int hashCode() {
return 100;
}*/
@Override
public String toString() {
return "age = " + age;
}
@Override
public boolean equals(Object obj){ // obj = person 多态
if(obj instanceof Person) {
Person per = (Person) obj;
return this.age == per.age;
}
return false;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
五. String类
(一) String类概述
- String类: 字符串类型,属于java.lang包,使用不需要导包.
- String类代表字符串.Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现.
- 在Java中只要使用双引号引用起来的任何数据它们都是String的一个对象.
- 字符串字面值属于常量,存储在方法区的常量池中,在创建之后就无法更改(是一个不可
变的字符序列).但是它们可以被共享. - 字符串在效果上,可以看做是字符数组,但实质上是字节数组.
public class Demo6 {
public static void main(String[] args) {
String s = "abc";
String s1 = "abc";
System.out.println(s == s1); // true
//常量池:当存储一个字符串对象时,首先判断是否有该数据,如果直接使用,没有才存储。
s = "123";
System.out.println(s.toString()); //字符串没有变,改变的是引用的指向。
}
}
/*
* String:
* final类,不可以有子类。
* Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现,意味着不需要关键字new就可以创建对象。
* 字符串是常量;它们的值在创建之后不能更改。因为 String 对象是不可变的,所以可以共享。
* 字符串的底层原理就是字符数组,字符串有下标。
* */
(二) String类的常用构造方法
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo7 {
public static void main(String[] args) throws UnsupportedEncodingException {
//构造方法
String s = new String(); //空字符序列
String s1 = new String("abc"); //两个对象,一个在堆,一个在常量池
//String s = "abc"; String s1 = new String("abc"); 区别。
//将字节数数组转为字符串
byte[] buf = {97,98,99,100};
String s2 = new String(buf); //采用平台默认的编码表 ---解码
System.out.println(s2);
//将字节数组的一部分转为字符串 参数:数组 下标 个数
String s3 = new String(buf,0,2);
System.out.println(s3);
//将字符数组转为字符串
char[] ch = {'a','b','c','d'};
String s4 = new String(ch);
System.out.println(s4);
String s5 = new String(ch,2,2);
System.out.println(s5);
//StringIndexOutOfBoundsException 字符串下标越界异常
byte[] bytes = {-28, -67, -96, -27, -91, -67};
String s6 = new String(bytes); //平台默认utf-8
String s7 = new String(bytes,"gbk"); //指定字符集 解码
System.out.println(s7);
// byte[] bytes = "你好".getBytes();
// System.out.println(Arrays.toString(bytes));
}
}
(三) 字符串的比较规则
- public boolean equals(Object anObject):String类重写的方法,判断两个字符串的内容(字符序列)是否相等
- == : 在比较基本类型的时候,比较的是数据的值,比较引用类型时,比较的是地址值是否相等.
案例1:
分析以下程序,判断控制台上的输出结果是什么:
String s1 = “abc”;
String s2 = “abc”;
String s3 = new String(“abc”);
String s4 = new String(“abc”);
System.out.println(s1 == s2); // true
System.out.println(s3 == s4); // false
System.out.println(s1.equals(s2)); // true
System.out.println(s3.equals(s4)); // true
(四) 字符串的常用方法
1.1 String类的获取和查找功能
- length() : 获取到一个字符串中的字符个数(字符串的长度) , 返回值类型int
- charAt(int index): 将字符串中指定的index索引位置上对应的字符获取到,返回值类型char
- subString(int beginIndex): 截取出字符串的一部分,从beginIndex索引开始, 到最后的全部字符序列取出来, 返回值结果,新的字符串String
- subString(int beginIndex, int endIndex) : 从beginIndex到endIndex-1之间的字符序列截取成一个新的字符串, 返回值结果String
注意 : JDK的方法中, 如果是对于两个索引位置进行操作, 通常包括开始索引, 不包括结束索引 - indexOf(String str) : 获取参数字符串str在方法调用字符串中第一次出现的索引位置
返回值类型int, 如果没有找到参数str存在位置, 返回-1 - indexOf(String str, int formIndex):返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索, 返回值类型int, 如果没有找到参数str存在位置, 返回-1
- lastIndexOf(String str) : 获取参数字符串str在方法调用字符串中最后一次出现的索引位置
返回值类型int, 如果没有找到参数str存在位置, 返回-1 - indexOf(int ch):返回指定字符(括号里可以写char类型,也就是字符串内的某个字符,比int占用字节少就行,自动强转)第一次出现的字符串内的索引
- indexOf(int ch, int fromIndex):返回指定字符第一次出现的字符串内的索引,以指定的索引开始搜索
public class Demo9 {
public static void main(String[] args) {
String s = "abcadefghijk";
//根据索引,返回字符,如果索引不存在,会抛出越界异常StringIndexOutOfBoundsException
char c = s.charAt(2);
System.out.println(c);
//根据字符,返回第一次出现的索引值,找不到返回-1
int index = s.indexOf('a');
System.out.println(index);
//根据字符,从指定位置向后查找第一次出现的索引值,找不到返回-1
index = s.indexOf('z',1);
System.out.println(index);
//查找字符串第一次出现的索引,找不到返回-1
index = s.indexOf("def");
System.out.println(index);
index = s.indexOf("def",5);
System.out.println(index);
//查找字符最后一次出现的索引,找不到返回-1
index = s.lastIndexOf('a');
System.out.println(index);
//其他三个方法自己演示。
//返回值字符串的长度
System.out.println(s.length()); //字符个数
//获取子字符串
String str = s.substring(0); //指定位置到末尾
System.out.println(str);
str = s.substring(0,5); //截取区间 ,包含左,不包含右
System.out.println(str);
}
}
1.2 String类中的判断功能
- equalsIgnoreCase(String anotherString) : 将调用方法字符串与参数列表中的字符串进行内容比较,不考虑字母大小写。
- startsWith(String s) : 调用方法字符串是否以参数s字符串为开始(前缀)
- endsWith(String s): 调用方法字符串是否以参数s字符串为结束(后缀)
- isEmpty(): 验证调用方法的字符串是不是一个空字符串””, 如果是空字符串返回true, 否则返回false
public class Demo8 {
public static void main(String[] args) {
String s = "helloworld123.txt";
//是否包含指定的字符序列
System.out.println( s.contains("hello"));
//是否以指定内容结尾
System.out.println(s.endsWith("txt"));
//是否以指定内容开头
System.out.println(s.startsWith("h"));
//比较字符串内容是否相同
System.out.println(s.equals("helloworld123.txt"));
//比较字符串内容是否相同,忽略大小写
System.out.println(s.equalsIgnoreCase("Helloworld123.txt"));
//字符串是否为空,空指的是字符串的长度是否为0,不是null,不空返回false
System.out.println(s.isEmpty());
}
}