P169 多态
指同一对象,在不同时刻表现出来的不同形态。
多态的前提和体现
- 有继承/实现关系
- 有方法重写
- 有父类引用指向子类对象
成员访问特点
- 成员变量:编译看左边,执行看右边
- 成员方法:编译看右边(anamial),执行看左边(dog的函数)
多态的好处
- 提高程序的拓展性:定义方法时把父类定义为参数,在将来使用时则使用子类进行具体操作。
- 多态的弊端:不能使用子类的特有功能。
向上转型和向下转型
//下面就是多态 //下面就是多态
Animal a = new Cat(); // 也叫做向上转型
Cat ca = (Cat) a;
ca.eat(); // 向下转型
ca.playGame(); // 可以访问cat的独自的方法
多态转型内存图解
P175 抽象类
定义方法
抽象类和抽象函数都要用abstract来修饰;抽象类可以用非抽象方法。
public abstract class Animal {
/*public void eat(){
System.out.println("吃东西");
}*/
public abstract void eat(); // 不给出方法体,定义为抽象的方法
}
抽象类的特点
- 抽象类和抽象方法必须使用abstract关键字来修饰
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。
- 抽象类不能实例化,但可以通过多态的方式,通过子类对象实例化来进行实例化,叫做抽象多态
- 抽象类的子类要么是抽象类,要么抽血抽象类中的所有抽象方法。
抽象类的成员特点
- 可以有成员变量,可以是常量,可以是变量
- 构造方法:有构造方法,用于子类访问父类数据的初始化。但不能实例化
- 成员方法:可以有抽象方法,限制子类必须完成某些动作;可以有非抽象方法,提高代码复用性
P179 接口
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用,Java中的接口更多的体现再对行为的抽象
接口的特点
- 接口用interface修饰
- 类实现接口用implement表示
- 接口不能实例化,参考多态的方式:通过实现类对象实例化,叫接口多态,多态的形式:具体类多态,抽象类多态,接口多态。
- 接口实现类要么是抽象类,要么重写接口中的所有抽象方法。
public interface Jumping {
public abstract void jump();
}
public class Cat implements Jumping{
@Override
public void jump() {
System.out.println("cat is jumping..");
}
}
public abstract class Dog implements Jumping{
}
-------------------测试文件-------------------------
public static void main(String[] args) {
// Jumping j = new Jump(); // 不能实例化接口
Jumping j = new Cat();
j.jump();
}
接口的成员特点
接口和类的关系
抽象类和接口的区别
运动员和教练的案例
主要是学习设计类的思维的:从具体到抽象。
P187 类名作为形参和返回值&&抽象类名作为形参和返回值&&接口名作为形参和返回值
- 方法的形参是类名,其实需要的是该类的对象
- 方法的返回值是类名,其实返回的是该类的对象
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象。
- 方法的形参是接口名,其实需要的是该接口的实现类对象。
- 方法的返回值是接口名,其实返回的是该接口的实现类对象。
P189 内部类
内部类就是再一个类中定义了一个类。
内部类的访问特点
- 内部类可以直接访问外部类,包括私有。
- 外部类要访问内部类的成员,必须创建对象。
- 根据内部类再类中定义的位置不同,可以分为成员内部类和局部内部类
public class Outer {
private int num = 10;
public class Inter{
public void show(){
System.out.println(num); // 可以访问外部对象的私有
}
}
public void method(){
Inter i = new Inter();
i.show(); // 外部类访问内部必须通过对象来实现
}
}
成员内部类
外界创建成员内部类的格式:
外部类.内部类 对象名 = 外部类对象.内部类对象
Outer.Inner oi = new Outer().new Inter();
但是我们定义内部类的目的一般是不希望外部使用的,所以一般使用private来修饰内部类,则上述的使用方法将报错,这个时候,在外部类通过方法实现对内部类的相关的操作
public void method(){
Inter i = new Inter();
i.show(); // 外部类访问内部必须通过对象来实现
}
局部内部类
局部内部类是在方法中定义的类,所以外界是无法直接使用,需要再方法内部创建对象并使用,该类可以直接访问外部类的成员,也可以访问方法内的局部变量
public void method(){
Inter i = new Inter();
i.show(); // 外部类访问内部必须通过对象来实现
}
public void method_inter(){
int num2 = 20;
class temp{
public void show(){
System.out.println(num);
System.out.println(num2);
}
}
temp t = new temp();
t.show();
}
匿名内部类
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
格式:
本质:是一个继承了该类或者实现了该接口的子类匿名对象
new 类名或者接口名(){
重写方法;
};
new Inter(){
public void show(){
}
}
示例代码
---------------------------------------------
public interface Interface {
void show();
}
-----------------------------------------------------
public class OuterNullName {
public void method(){
// 下面这个就实现 了匿名对象 并调用了show方法
new Interface(){
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
// 下面是第二次调用show方法,每次调用都要这么这。。
new Interface(){
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
---------------------------------------------------------------------------
// 对于多次调用的话,为了不像上面那么繁琐,可以这样:
Interface i = new Interface(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
i.show();
}
}
匿名内部类再开发的使用
…略
常用API
P194 Math
System.out.println(Math.abs(88));
System.out.println(Math.abs(-88));
System.out.println("--------注意下面ceil方法返回的是double类型-----------");
System.out.println(Math.ceil(12.34));
System.out.println(Math.ceil(12.56));
System.out.println("----------------------------");
System.out.println(Math.floor((12.34)));
System.out.println(Math.floor(12.56));
System.out.println("----------------------");
System.out.println(Math.round(12.34F));
System.out.println(Math.round(12.56F));
System.out.println("--------------------");
System.out.println(Math.max(23,15));
System.out.println(Math.min(24,12));
System.out.println(Math.pow(2.0,3.0));
System.out.println(Math.random());
System.out.println(Math.random()*100);
P195 System常用API
public static void main(String[] args) {
System.out.println("开始");
System.out.println(System.currentTimeMillis());
System.out.println("距离1970年:" + System.currentTimeMillis()*1.0 / 1000/60/60/24/365 +"年");
// 计算程序运行时间
long start = System.currentTimeMillis();
for(int i=0;i<10000;++i){
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println("共耗时:"+(end - start) + "ms");
System.exit(0); // 在这里就终止了,程序将不往下执行就
System.out.println("结束");
}
P195 Object类_tostring方法
Object类是类层次结构的根,每个类都可以将Object作为超类,所有的类都直接或者简介的继承该类
构造方法 public Object()
子对象的构造方法默认访问的是父类的无参构造方法,因为他们的顶级父类只有无参构造方法
建议所有子类重写该方法
P196 Ojbect类的equals方法
这个也是建议重写,首先通过alt+insert
键:
选择equals()那个,然后一直next就行,生成代码后可以吧hashCode()给删除了,注意类中应该有get…等方法
@Override
public boolean equals(Object o) {
if (this == o) return true; // 首先判断地址是否相同
if (o == null || getClass() != o.getClass()) return false; //判断参数是否为null和两个对象是否是一个类
//向下转型
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
P200 Arrays类的概述和常用方法
工具类的设计思想
- 构造方法用private修饰
- 成员用public static修饰
public static void main(String[] args) {
int[] arr = {5,3,2,8,9,6,1,4};
System.out.println("before sort:" + Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("after sort"+ Arrays.toString(arr));
}
P201 包装类
以Integer为例
Integer i1 = new Integer(100);
// 注意Integer重写了toString方法
System.out.println(i1);
Integer i2 = new Integer("100");
System.out.println(i2);
//上面已经过时了,推荐使用下面的方法
Integer i3 = Integer.valueOf(100);
System.out.println(i3);
Integer i4 = Integer.valueOf("100");
System.out.println(i4);
P202 int和string的相互转换
// int ------>string
//way 1
int num = 100;
String s1 = num + " ";
//way 2
String s2 = String.valueOf(num);
System.out.println(s1);
System.out.println(s2);
System.out.println("--------------------------");
//string ------>int
//way 1:string --->Integer---->int
String s = "134";
Integer i = Integer.valueOf(s);
int si = i.intValue(); // Interger的值作为返回内容,为int类型
System.out.println(si);
//way 2
int si2 = Integer.parseInt(s);
System.out.println(si2);
P205 装箱和拆箱
装箱就是把基本数据类型转化为对应的包装类类型
拆箱就是把包装类类型转换为对应的基本数据类型
Integer ii = Integer.valueOf(100); // 装箱
Integer ii2 = 100; // 自动装箱 底层还是上面的方法
ii2 = ii2.intValue() + 200; // intValue的动作是拆箱
ii2 +=200 ; // 自动拆箱
System.out.println(ii2);
Integer iii = null;
if(iii !=null)
iii +=300; // NullPointerException
P206 Date类
import java.util.Date;
构造方法和常用方法
Date d1 = new Date();
System.out.println(d1);// Mon Dec 13 14:51:41 CST 2021
long date = 1000*60* 60;
Date d2 = new Date(date);
System.out.println(d2); // Thu Jan 01 09:00:00 CST 1970
Date d1 = new Date();
System.out.println(d1.getTime());// 获取从日期到1970.1.1 00:00到现在的毫秒值
System.out.println(d1.getTime() * 1.0 / 1000/60/60/24/365); // year
long time = 1000*60*60;
long time2 = System.currentTimeMillis();
d1.setTime(time);
System.out.println(d1);
P208 SimpleDateFormat类
对日期进行格式化和解析
public static void main(String[] args) throws ParseException {
//date --->string
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(); // 无参构造
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH-mm-ss");
String s = sdf.format(d);
String s2 = sdf2.format(d);
System.out.println(s);
System.out.println(s2);
//string--->date
String ss = "2048-08-09 11:11:11";
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf3.parse(ss);
System.out.println(dd);
}
P210 Calendar类
注意month+1
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR,3); // 三年后
c.add(Calendar.DATE,5); // 5天后
c.set(2039.11, 2); // 设置当前的时间
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MARCH)+1;
int date = c.get(Calendar.DATE);
System.out.println(c);
System.out.println(year + "nian" + month + "yue" + date+"ri");
}
}
P201 异常
JVM的默认异常处理方案
try…catch…捕获异常及Throwable常用成员方法
try {
System.out.println(arr[3]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("你访问的数组index不存在");
e.printStackTrace(); // 最常用
e.getMessage(); // 返回异常出现的原因
System.out.println(e.toString()); // 返回可抛出的简短的描述
}
- 编译时异常:必须显示处理,否则程序就发生错误,不能通过编译(编译时异常意思是有可能出异常)
- 运行时异常:无须显示处理,也可以和编译时异常一起处理
throws异常抛出
这种只是做了抛出异常,若想程序继续往下执行,那还得用try…catch…来处理
//编译时异常
public static void method3() throws ParseException {
String s = "2038-1-2";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
}
// 运行时异常
public static void method2()throws ArrayIndexOutOfBoundsException{
int[] arr = {1,2,3};
System.out.println(arr[3]);
}
自定义异常
throws和throw的区别
P220 集合体系结构
Collection常用的方法
Collection<String> c = new ArrayList<String>();
c.add("hello");
c.add("world");
c.add("java");
System.out.println(c);
System.out.println(c.add("return true"));
System.out.println(c);
c.remove("java");
System.out.println(c);
System.out.println(c.contains("world"));
// 迭代器的使用
Iterator<String> it = c.iterator(); // 获得迭代器
//it.next()得到迭代中的下一个元素,注意不能超过范围,否则抛出异常
//System.out.println(it.next());
//System.out.println(it.next());
//一般这个样子使用
while(it.hasNext()) {
String s = it.next();
System.out.println(s);
}
P227 List
list特有方法
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);
list.add(2,"javecc");
String dead = list.remove(2);
System.out.println(dead);
list.set(1,"javaeee");
System.out.println(list.get(1));
for(int i=0;i<list.size();++i){
String s = list.get(i);
System.out.println(s);
}
// 迭代器的方式遍历
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
并发修改异常
主要是迭代器的方法如果在迭代过程中出现了插入的新元素,就会出问题。
列表迭代器
通过list迭代器不会出现并发修改异常
ListIterator<String> lit = list.listIterator();
while(lit.hasNext()){
String s = lit.next();
if(s.equals("world")){
lit.add("javaee");
}
}