Java13天进阶教程【第3天】

第3天

1.多态

目标:多态的入门概述。

面向对象的三大特征:封装,继承,多态。

多态的形式

​ 父类类型 对象名称 = new 子类构造器;

​ 接口 对象名称 = new 实现类构造器;

​ 父类类型的范围 > 子类类型范围的。

多态的概念

​ 同一个类型的对象,执行同一个行为,在不同的状态下会表现出不同的行为特征。

多态的识别技巧

​ 对于方法的调用:编译看左边,运行看右边。

​ 对于变量的调用:编译看左边,运行看左边。

多态的使用前提

​ (1) 必须存在继承或者实现关系。

​ (2) 必须存在父类类型的变量引用子类类型的对象。

​ (3) 需要存在方法重写。

小结

​ 记住多态的形式,识别,概念等语法即可!

public class PolymorphicDemo {
    public static void main(String[] args) {
        //  父类类型 对象名称 = new 子类构造器;
        Animal dlam = new Cat();
        dlam.run(); // 对于方法的调用:编译看左边,运行看右边。
        System.out.println(dlam.name); // 对于变量的调用:编译看左边,运行看左边。

        Animal taiDi = new Dog();
        taiDi.run(); // 对于方法的调用:编译看左边,运行看右边。
        System.out.println(taiDi.name); // 对于变量的调用:编译看左边,运行看左边。
    }
}

class Dog extends Animal{
    public String name = "🐶名称Dog";
    @Override
    public void run(){
        System.out.println("🐕跑的贼快~~~~!");
    }
}

class Cat extends Animal{
    public String name = "🐱名称Cat";
    @Override
    public void run(){
        System.out.println("🐱跑的飞快~~~~!");
    }
}

class Animal{
    public String name = "动物名称Animal";
    public void run(){
        System.out.println("动物跑!");
    }
}

目标:多态的优劣势。

优势

​ 1.在多态形式下,右边对象可以实现组件化切换,业务功能也随之改变,

​ 便于扩展和维护。可以实现类与类之间的解耦。

​ 2.实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,

​ 可以传入一切子类对象进行方法的调用,更能体现出多态的扩展性与便利。

劣势

​ 1.多态形式下,不能直接调用子类特有的功能。编译看左边!! 左边

​ 父类中没有子类独有的功能,所以代码在编译阶段就直接报错了!

小结

​ 记住以上语法!


目标:引用数据类型的自动类型转换。

在基础班学过了基本数据类型的转换。

​ 1.小范围类型的变量或者值可以直接赋值给大范围类型的变量。

​ 2.大范围类型的变量或者值必须强制类型转换给小范围类型的变量。

image-20200712162749563

引用数据类型转换的思想是一样的:

​ 父类类型的范围 > 子类类型的范围。

​ Animal Cat

引用数据类型的自动类型转换语法:

​ 1.子类类型的对象或者变量可以自动类型转换赋值给父类类型的变量。

小结:

​ 记住语法!

​ 引用类型的自动类型转换并不能解决多态的劣势。

// 1.引用类型的自动类型转换:小范围的对象赋值给大范围的变量
Animal a = new Cat();

class Animal{}
class Cat extends Animal{}

目标:引用类型强制类型转换

引用类型强制类型转换的语法

​ 1.父类类型的变量或者对象必须强制类型转换成子类类型的变量,否则报错!

强制类型转换的格式

​ 类型 变量名称 = (类型)(对象或者变量)

注意:有继承/实现关系的两个类型就可以进行强制类型转换,编译阶段一定不报错!

​ 但是运行阶段可能出现:类型转换异常 ClassCastException

Java建议在进行强制类型转换之前先判断变量的真实类型,再强制类型转换!

变量 instanceof 类型: 判断前面的变量是否是后面的类型或者其子类类型才会返回true,

小结

​ 有继承/实现关系的两个类型就可以进行强制类型转换,编译阶段一定不报错!

​ 但是运行阶段可能出现:类型转换异常 ClassCastException

​ Java建议在进行强制类型转换之前先判断变量的真实类型,再强制类型转换!

​ 变量 instanceof 类型: 判断前面的变量是否是后面的类型或者其子类类型才会返回true,

// 2.多态下类型转换异常问题研究(重点)
Animal a1 = new Cat();
Wolf w1 = (Wolf) a1; // 编译阶段没有报错!在运行阶段出现ClassCastException类型转换成!

if(a1 instanceof Cat){
    Cat c1 = (Cat) a1;
    c1.catchMouse();
}else if(a1 instanceof Wolf){
    Wolf w1 = (Wolf) a1;
    w1.catchSheep();
}

2.内部类

目标:内部类的概述和分类。

内部类是类的五大成分之一:成员变量,方法,构造器,代码块,内部类。

什么是内部类?

​ 定义在一个类里面的类就是内部类。

内部类有什么用?

​ 可以提供更好的封装性, 内部类有更多权限修饰符 , 封装性有更多的控制。

​ 可以体现出组件的思想。

内部类的分类:

​ (1)静态内部类。

​ (2)实例内部类。(成员内部类)

​ (3)局部内部类。

​ (4)匿名内部类。(重点)

小结

​ 匿名内部类是我们的重点。


目标:静态内部类的研究(了解语法即可)

什么是静态内部类?

​ 有static修饰,属于外部类本身,会加载一次。

静态内部类中的成分研究

​ 类有的成分它都有,静态内部类属于外部类本身,只会加载一次

​ 所以它的特点与外部类是完全一样的,只是位置在别人里面而已。

​ 外部类=宿主

​ 内部类=寄生

静态内部类的访问格式

​ 外部类名称.内部类名称

静态内部类创建对象的格式

​ 外部类名称.内部类名称 对象名称 = new 外部类名称.内部类构造器;

静态内部类的访问拓展

​ 静态内部类中是否可以直接访问外部类的静态成员?可以的,外部类的静态成员只有一份,可以被共享!

​ 静态内部类中是否可以直接访问外部类的实例成员?不可以的,外部类的是成员必须用外部类对象访问!!

小结

​ 静态内部类属于外部类本身,只会加载一次

​ 所以它的特点与外部类是完全一样的,只是位置在别人里面而已。

class Outter{
    public static int age1 = 12;
    private double salary;

    // 静态内部类:有static修饰,属于外部类本身,只会加载一次
    public static class Inner{
        public void show() {
            System.out.println(age1);//12
            System.out.println(salary);//访问不到
        }
    }
}
public class InnerClass {
    public static void main(String[] args) {
        // 外部类名称.内部类名称 对象名称 = new 外部类名称.内部类构造器
        Outter.Inner in = new Outter.Inner();
        in.show();
    }
}

目标:内部类_实例内部类(成员内部类)(了解语法为主)

什么是实例内部类

​ 无static修饰的内部类,属于外部类的每个对象的,跟着对象一起加载的。

实例内部类的成分特点

​ 实例内部类中不能定义静态成员,其他都可以定义。

​ 可以定义常量。

实例内部类的访问格式

​ 外部类名称.内部类名称。

创建对象的格式

​ 外部类名称.内部类名称 对象名称 = new 外部类构造器.new 内部构造器;

拓展

​ 实例内部类中是否可以直接访问外部类的静态成员?可以的,外部类的静态成员可以被共享访问!

​ 实例内部类中是否可以访问外部类的实例成员?可以的,实例内部类属于外部类对象,可以直接访问当前外部类对象

的实例成员!

小结:

​ 实例内部类属于外部类对象,需要用外部类对象一起加载,

​ 实例内部类可以访问外部类的全部成员!


目标:局部内部类。(几乎不用)

定义在方法中,在构造器中,代码块中,for循环中定义的内部类,就是局部内部类。

局部内部类中的成分特点

​ 只能定义实例成员,不能定义静态成员

​ 可以定义常量的。

小结

​ 局部内部类没啥用。

public static void test(){
   class Animal{
   }

   class Cat extends Animal{
   }
}

目标:匿名内部类的概述

什么是匿名内部类?

​ 就是一个没有名字的局部内部类。

​ 匿名内部类目的是为了:简化代码,也是开发中常用的形式。

匿名内部类的格式

​ new 类名|抽象类|接口(形参){

​ 方法重写。

​ }

匿名内部类的特点

​ 1.匿名内部类是一个没有名字的内部类。

​ 2.匿名内部类一旦写出来,就会立即创建一个匿名内部类的对象返回。

​ 3.匿名内部类的对象的类型相当于是当前new的那个的类型的子类类型

小结

​ 1.匿名内部类是一个没有名字的内部类。

​ 2.匿名内部类一旦写出来,就会立即创建一个匿名内部类的对象返回。

​ 3.匿名内部类的对象的类型相当于是当前new的那个的类型的子类类型。

public class Anonymity {
    public static void main(String[] args) {
        Animal a2 = new Animal() {
            @Override
            public void run() {
                System.out.println("人跑的快");
            }
        };
        a2.go();
    }
}
abstract class Animal{
    public abstract void run();
    public void go(){
        System.out.println("开始go~~~");
    }
}

3.包和权限修饰符

目标:包和权限修饰符。


分门别类的管理各种不同的技术。

​ 企业的代码必须用包区分。便于管理技术,扩展技术,阅读技术。

定义包的格式:package 包名; 必须放在类名的最上面。一般工具已经帮我们做好了。

包名的命名规范

​ 一般是公司域名的倒写+技术名称:
​ http://www.itheima.com => com.itheima.技术名称

​ 包名建议全部用英文,多个单词用”.“连接,必须是合法标识符,不能用关键字

注意

​ 相同包下的类可以直接访问。

​ 不同包下的类必须导包,才可以使用!

​ 导包格式:import 包名.类名;


目标:权限修饰符。

权限修饰符:有四种(private -> 缺省 -> protected - > public )

可以修饰成员变量,修饰方法,修饰构造器,内部类,不同修饰符修饰的成员能够被访问的权限将受到限制!

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

​ private 缺省 protected public

​ 本类中 √ √ √ √

​ 本包下其他类中 X √ √ √

​ 其他包下的子类中 X X √ √

​ 其他包下的类中 X X X √

4.Object类

目标:常用API的学习-Object类的toString方法使用详解。

引入

​ 包:java.lang.Object

​ Object类是Java中的祖宗类。

​ 一个类要么默认继承了Object类,要么间接继承了Object类。

​ Object类的方法是一切子类都可以直接使用的,所以我们要学习Object类的方法。

Object类的常用方法

​ (1)public String toString():

​ – 默认是返回当前对象在堆内存中的地址信息:com.itheima._12Object类的详细使用.Student@735b478

​ – 默认的地址信息格式:类的全限名@内存地址

​ – 直接输出对象名称,默认会自动调用toString()方法,所以输出对象toString()调用可以省略不写

​ – 开发中直接输出对象,默认输出对象的地址其实是毫无意义的。开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息!所以父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息输出!!

小结:

​ toString()默认是返回当前对象在堆内存中的地址信息:

​ 开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息!

​ 所以父类toString()方法存在的意义就是为了被子类重写,重写toString可以看到对象的内容信息。

​ (2)public boolean equals(Object o):

​ – 默认是比较两个对象的地址是否相同。相同返回true,反之。

​ – 直接比较两个对象的地址是否相同完全可以用“==”替代equals。所以equals存在的意义是为了被子类重写,以便程序员可以自己来定制比较规则。

​ – 需求:只要两个对象的内容一样,我们就认为他们是相等的。

小结

​ equals存在的意义是为了被子类重写,以便程序员可以自己来定制比较规则。


目标:Objects类的使用。

Objects类与Object还是继承关系。

Objects类是从JDK 1.7开始之后才有的。

Objects的方法

​ 1.public static boolean equals(Object a, Object b)

​ – 比较两个对象的。

​ – 底层进行非空判断,从而可以避免空指针异常。更安全!!推荐使用!!

​ public static boolean equals(Object a, Object b) {

​ return a == b || a != null && a.equals(b);
​ }

​ 2.public static boolean isNull(Object obj)

​ – 判断变量是否为null ,为null返回true ,反之!

Student s1 = null;
Student s2 = new Student();
System.out.println(Objects.equals(s1 , s2)); // 可以避免空指针异常。更安全!! false
// System.out.println(s1.equals(s2)); // 空指针异常

// 询问s1是否为null 为null返回true ,反之!
System.out.println(Objects.isNull(s1));
System.out.println(s1 == null); // 可以直接用==判断也可以!

5.Date日期类

目标:Date日期类的使用。

Java是面向对象的,会用一个类代表一个事物。

Date类在Java中代表的是系统当前此刻日期时间对象。

Date类

​ 包:java.util.Date。

​ 构造器:

​ – public Date():创建当前系统的此刻日期时间对象。

​ – public Date(long time):

​ 方法:
​ – public long getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来走过的总的毫秒数。

​ 时间记录的两种方式:

​ a.Date日期对象。

​ b.时间毫秒值:从1970-01-01 00:00:00开始走到此刻的总的毫秒值。 1s = 1000ms

小结

​ Date可以代表系统当前此刻日期时间对象。

​ 时间记录的两种方式:

Date日期对象。

时间毫秒值:从1970-01-01 00:00:00开始走到此刻的总的毫秒值。 1s = 1000ms
// a.创建一个日期对象代表了系统此刻日期时间对象
Date d = new Date();
System.out.println(d); //Sun Aug 07 10:36:56 CST 2022

// b.拿当前日期对象的时间毫秒值
long time = d.getTime();
System.out.println(time);

目标:Date类的有参数构造器的使用。

​ 构造器:

​ – public Date():创建当前系统的此刻日期时间对象。

​ – public Date(long time):把时间毫秒值转换成日期对象。

​ 流程:

​ Date日期对象 -> getTime() -> 时间毫秒值

​ 时间毫秒值 -> new Date(时间毫秒值) -> Date日期对象

小结

​ public Date(long time):把时间毫秒值转换成日期对象。

// 需求:问121s以后的时间是多少。

// 1.拿到此刻日期对象
Date d = new Date();
System.out.println(d);

// 2.拿到此刻日期对象的时间毫秒值 往后走 121 s
long time = d.getTime() + 121*1000;

// 3.把时间毫秒值转换成日期对象。
Date d1 = new Date(time);
System.out.println(d1);

6.DateFormat日期格式化类

目标:DateFormat简单日期格式化类的使用。

引入

​ 我们之前得到的Date日期对象或者时间毫秒值的时间形式

​ 开发中并不喜欢,不符合有些时间格式的需求。

DateFormat作用

​ 1.可以把“日期对象”或者“时间毫秒值”格式化成我们喜欢的时间形式。(格式化时间)

​ 2.可以把字符串的时间形式解析成日期对象。(解析字符串时间)

DateFormat是一个抽象类,不能直接使用,要找它的子类:SimpleDateFormat

我们需要用的是简单日期格式化类:SimpleDateFormat

SimpleDateFormat简单日期格式化类

​ 包:java.text.SimpleDateFormat

​ 构造器:public SimpleDateFormat(String pattern):

​ 指定时间的格式创建简单日期格式化对象。

​ 方法:

​ – public String format(Date date):可以把日期对象格式化成我们喜欢的时间形式,返回的是字符串!

​ – public String format(Object time):可以把时间毫秒值格式化成我们喜欢的时间形式,返回的是字符串!

​ – public Date parse(String date) throws ParseException:把字符串的时间解析成日期对象

小结

​ 简单日期格式化类SimpleDateFormat可以把日期对象格式化成我们喜欢的时间形式

​ – public String format(Date date):可以把日期对象格式化成我们喜欢的时间形式,返回的是字符串!

// 需求:把此刻日期对象格式化成我们喜欢的形式。
// 1.得到此刻日期对象
Date d = new Date();

// 2.创建一个简单日期格式化对象负责格式化日期对象
// 注意:参数是之间的格式。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");

// 3.开始调用方法格式化时间得到格式化的字符串时间形式
String rs = sdf.format(d);
System.out.println(rs); //2022年08月07日 15:24:54 周日 下午

拓展:简单日期格式化类SimpleDateFormat格式化时间毫秒值。

// 1.问121s后的时间是多少。格式化输出。
// a.得到此刻日期对象
Date date = new Date();

// b.得到当前时间的时间毫秒值
long time = date.getTime();
time += 121 * 1000;

// c.格式化时间毫秒值
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
System.out.println(sdf.format(time));

目标:简单日期格式化类SimpleDateFormat解析字符串时间成为日期对象。

引入

​ Date日期对象 -> 格式化成 -> 喜欢的字符串时间形式。

​ 时间毫秒值 -> 格式化成 -> 喜欢的字符串时间形式。

​ 字符串的时间形式 -> 解析成 -> Date日期对象。

​ 开发中经常会收到字符串的时间,需要转成Date日期对象。"2018-10-11 10:10:22"字符串转换成Date日期对象

// 面试题:请问 “2019-11-04 09:30:30” 往后 1天15小时,30分29s后的时间是多少
// a.定义一个字符串时间
String date = "2019-11-04 09:30:30";

// b.把字符串的时间解析成Date日期对象 。(重点)
// 1.创建一个简单日期格式化对象负责解析字符串的时间成为日期对象
// 注意:参数必须与被解析的时间的格式完全一致,否则执行报错!!
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 2.开始解析成日期对象
Date newDate = sdf.parse(date);

// c.得到日期对象的时间毫秒值 + 往后走 1天15小时,30分29s
long time = newDate.getTime() + (24L *60*60 + 15*60*60 + 30*60 + 29) * 1000;

// d.把时间毫秒值格式化成喜欢的字符串的时间形式!
System.out.println(sdf.format(time));

7.Calendar日历类

目标:日历类Calendar的使用。

Calendar代表了系统此刻日期对应的日历对象。

Calendar是一个抽象类,不能直接创建对象。

Calendar日历类创建日历对象的语法:

​ Calendar rightNow = Calendar.getInstance();

Calendar的方法

​ 1.public static Calendar getInstance(): 返回一个日历类的对象。

​ 2.public int get(int field):取日期中的某个字段信息。

​ 3.public void set(int field,int value):修改日历的某个字段信息。

​ 4.public void add(int field,int amount):为某个字段增加/减少指定的值

​ 5.public final Date getTime(): 拿到此刻日期对象。

​ 6.public long getTimeInMillis(): 拿到此刻时间毫秒值

小结

​ 记住。

// 1.通过调用日历类的静态方法getInstance得到一个当前此刻日期对象对应的日历对象。
Calendar rightNow = Calendar.getInstance();
System.out.println(rightNow);

// 2.获取年:
int year = rightNow.get(Calendar.YEAR);
System.out.println(year);

int mm = rightNow.get(Calendar.MONTH) + 1;
System.out.println(mm);

// 3.一年中的第几天: 308
int days = rightNow.get(Calendar.DAY_OF_YEAR);
System.out.println(days);

// 4.修改日历的信息
//rightNow.set(Calendar.YEAR , 2099);
//System.out.println(rightNow.get(Calendar.YEAR));

// 5.日历可以得到此刻日期对象。
Date d = rightNow.getTime();
System.out.println(d);

// 6.此刻时间毫秒值
long time = rightNow.getTimeInMillis();
System.out.println(time);

// 7.请问701天  15小时后是哪个日期
// 让日历的一年中的第几天往后走 701天!
rightNow.add(Calendar.DAY_OF_YEAR , 701);
rightNow.add(Calendar.HOUR , 15);
long time1 = rightNow.getTimeInMillis();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
System.out.println(sdf.format(time1));

8.Math类

目标:Math类的使用。

Math用于做数学运算。

Math类中的方法全部是静态方法,直接用类名调用即可。

方法

​ 方法名 说明

​ public static int abs(int a) 获取参数a的绝对值

​ public static double ceil(double a) 向上取整

​ public static double floor(double a) 向下取整

​ public static double pow(double a, double b) 获取a的b次幂

​ public static long round(double a) 四舍五入取整

​ public static int max(int a, int b) 返回两个int的较大值

​ public static int min(int a, int b) 返回两个int的较小值

小结

​ 记住。

// 1.取绝对值:返回正数。
System.out.println(Math.abs(10));
System.out.println(Math.abs(-10.3));
// 2.向上取整: 5
System.out.println(Math.ceil(4.00000001)); // 5.0
// 3.向下取整:4
System.out.println(Math.floor(4.99999999)); // 4.0
// 4.求指数次方
System.out.println(Math.pow(2 , 3)); // 2^3 = 8.0
// 5.四舍五入 10
System.out.println(Math.round(4.49999)); // 4
System.out.println(Math.round(4.500001)); // 5

9.System类

目标:System系统类的使用。

System代表当前系统。

静态方法

​ 1.public static void exit(int status):终止JVM虚拟机,非0是异常终止。

​ 2.public static long currentTimeMillis():获取当前系统此刻时间毫秒值。

​ 3.可以做数组的拷贝。

​ arraycopy(Object var0, int var1, Object var2, int var3, int var4);

  • 参数一:原数组
  • 参数二:从原数组的哪个位置开始赋值。
  • 参数三:目标数组
  • 参数四:赋值到目标数组的哪个位置
  • 参数五:赋值几个。

10.BigDecimal计算浮点型

目标:BigDecimal大数据类。

引入

​ 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。

​ BigDecimal可以解决浮点型运算数据失真的问题。

BigDicimal类

​ 包:java.math.

​ 创建对象的方式(最好的方式:)

​ public static BigDecimal valueOf(double val) :包装浮点数成为大数据对象。

​ 方法声明

​ public BigDecimal add(BigDecimal value) 加法运算

​ public BigDecimal subtract(BigDecimal value) 减法运算

​ public BigDecimal multiply(BigDecimal value) 乘法运算

​ public BigDecimal divide(BigDecimal value) 除法运算

​ public double doubleValue():把BigDecimal转换成double类型。

double a = 0.1 ;
double b = 0.2 ;
// 1.把浮点数转换成大数据对象运算
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(b1);  // 加法
BigDecimal c1 = a1.divide(b1); // 除法

// 结果可能需要继续使用!!!
// BigDecimal只是解决精度问题的手段,double数据才是我们的目的!!
double rs = c1.doubleValue();

11.包装类

目标:包装类。

引入

​ Java认为一切皆对象。引用数据类型就是对象了。

​ 但是在Java中8基本数据类型不是对象,只是表示一种数据的类型形式,这8种数据类型显得很突兀。

​ Java为了一切皆对象的思想统一,把8种基本数据类型转换成对应的类,这个类称为基本数据类型的包装类。

基本数据类型 包装类(引用数据类型)

​ byte Byte

​ short Short

​ int Integer(特殊)

​ long Long

​ float Float

​ double Double

​ char Character(特殊)

​ boolean Boolean

自动装箱:可以直接把基本数据类型的值或者变量赋值给包装类。

自动拆箱:可以把包装类的变量直接赋值给基本数据类型。

小结

​ 自动装箱:可以直接把基本数据类型的值或者变量赋值给包装类。

int a = 12 ;
Integer a1 = 12 ;  // 自动装箱
Integer a2 = a ;   // 自动装箱

Integer c = 100 ;
int c1 = c ;      // 自动拆箱

int d = 12;
Integer d1 = null; // 引用数据类型默认值为null
Integer d2 = 0;

Integer it = Integer.valueOf(12);  // 手工装箱!

Integer it3 = 111 ;
int it33 = it3.intValue(); // 手工拆箱
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值