javaSE基础知识笔记(四)

多态——面向对象三大特征之三

  • 同类型的对象,执行同一个行为,会表现出不同的行为特征

1 多态的常见形式

父类(或接口)类型new子类对象

	父类类型 对象名称 = new 子类构造器;
	接口 对象名称 = new 实现类构造器;

2 多态中成员访问特点(重点)

public abstract class Animal {
	public String name = "父类——动物";
	public abstract void eat();
}

class Dog extends Animal {
	public String name = "子类——狗";
	@Override
	public void eat() { System.out.println("狗吃骨头");}
}
  • 方法调用: 编译看左边,运行看右边
	Animal animal = new Dog();
	animal.eat(); // 运行结果:狗吃骨头
  • 变量调用: 编译看左边,运行看左边(多态侧重“行为”多态)
	Animal animal = new Dog();
	System.out.println(animal.name); // 运行结果:父类——动物

3 多态的前提

  • 有继承/实现关系
  • 有父类引用指向子类对象
  • 有方法重写

4 多态的特点

  • 在多态形式下,右边对象可以实现解耦合,便于扩展和维护
	Animal animal = new Dog();
	animal.eat();

可直接将new Dog()修改为new Cat(),后续业务行为随对象而变,后续代码无需修改

	Animal animal = new Cat();
	animal.eat();
  • 定义方法的时候,使用父类型作为参数,该方法就可以接收者父类的一切子类对象,体现出多态的扩展性与便利
	public void go(Animal a) {
		a.eat();
	}
	Animal a1 = new Dog();
	go(a1);
	Animal a2 = new Cat();
	go(a2);
  • 多态下不能使用子类的独有功能(子类有但父类没有的功能)

5 多态下引用数据类型的类型转换

5.1 自动类型转换(从子到父)

  • 子类对象赋值给父类类型的变量指向
//基础的多态定义即自动转型
Animal a = new Dog();

5.2 强制类型转换(从父到子)

  • 从父到子必须进行强制类型转换:
子类 对象变量 = (子类)父类类型的变量
  • 作用: 可以解决多态下的劣势,实现调用子类独有的功能(子类有但父类没有的功能)
	Animal a = new Dog();
	a.eat();
	Dog d = (Dog) a;
	d.狗类独有方法();
  • 注意: 如果转型后的类型和对象真实类型不是同一种类型时,编译不会报错,运行时会出现异常ClassCastException
	Animal a = new Dog();
	Cat c = (Cat) a; // 编译不会报错,运行时报异常
  • 此时使用 instanceof 判断当前对象的真实类型,再进行强制转换
变量名 instanceof 真实类型

内部类、常用API

1 内部类

1.1 概述

  • 内部类就是定义一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)

1.2 作用和使用场景

  • 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计
  • 内部类通常可以方便访问外部类的成员,包括私有成员
  • 内部类提供了更好的封装性,内部类本身就可以用pirvate、protected等修饰,封装性可以做更多控制

1.3 分类

  • 静态内部类 [了解]
  • 成员内部类 [了解]
  • 局部内部类 [了解]
  • 匿名内部类(重点)

1.3.1 静态内部类(了解)

  • 有static修饰,属于外部类本身
  • 静态内部类的特点和使用与普通类完全一样,类有的成分它都有,只是位置在别人里面
  • 创建格式:
public class Outer {
	// 静态成员内部类
	public static class Inner{
	}
}

  • 创建对象格式:
	外部类名.内部类名 对象名 = new 外部类名.内部类构造器;
	Outer.Inner in = new Outer.Inner();

  • 静态内部类的访问拓展

○静态内部类可以直接访问外部类的静态成员,因为外部类的静态成员只有一份可以被共享访问
○静态内部类不可以直接访问外部类的实例成员,因为外部类的实例成员必须用外部类对象访问

1.3.2 成员内部类(了解)

  • 无static修饰,属于外部类的对象
  • JDK16之后,成员内部类中可以定义静态成员
  • 创建格式:
public class Outer {
	// 成员内部类
	public class Inner {
	}
}
  • 创建对象格式:
外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
	Outer.Inner in = new Outer().new Inner();
  • 成员内部类的访问拓展:
  1. 成员内部类中可以直接访问外部类的静态成员
  2. 成员内部类的实例方法中可以直接访问外部类的实例成员,因为必须先有外部类对象,才能有成员内部类对象
  • 案例:
class People{
    private int heartbeat = 150;

    /**
       成员内部类
     */
    public class Heart{
        private int heartbeat = 110;

        public void show(){
            int heartbeat = 78;
            System.out.println(heartbeat); // 78
            System.out.println(this.heartbeat); // 110
            System.out.println(People.this.heartbeat); // 150
        }
    }
}

1.3.3 局部内部类(鸡肋语法,了解)

  • 局部内部类放在方法、代码块、构造器等执行体中
  • 局部内部类的类文件名为:外部类$N内部类.class(N为序号1,2,3…)

1.3.4 匿名内部类(重点)

  • 本质上是一个没有名字的局部内部类,定义在方法中、代码块中
  • 作用:方便创建子类对象,最终目的为了简化代码编写
  • 创建格式:
//通式
new 类|抽象类名|接口名() {
		@Override
		重写方法
	};
//举例
	Employee a = new Employee() {
		@Override
		public void work() {}
	};

  • 特点:

○匿名内部类是一个没有名字的内部类
○匿名内部类写出来就会产生一个匿名内部类的对象
○匿名内部类的对象类型相当于是当前new的那个类的子类类型
○匿名内部类编译后会产生class文件,即外部类$N.class(N为序号1,2,3…)

  • 常见使用形式:匿名内部类可以作为方法的实参进行传输
go(new Swimming() 
{
	@Override
	public void swim() { // TODO }
		});
  1. 给按钮绑定点击事件
// 为按钮绑定点击事件监听器
	btn.addActionListener(new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			// 点击事件
		}
	});
	
//可以优化为一行:btn.addActionListener(e -> 点击事件);
  • 总结:开发中不是我们主动去定义匿名内部类,而是别人需要我们写或者我们可以写的时候才会使用,匿名内部类的代码可以实现代码进一步的简化

2 Object、StringBuilder等常用API

2.1 Object

  • Object类的方法是一切子类对象都可以直接使用的
  • 一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类
  • 常用方法:

方法名

说明

public static boolean equals(Object a, Object b)

比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常。再进行equals比较

public static boolean isNull(Object obj)

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

2.1.1 toString方法

  • 父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
  • 用sout输出对象信息时".toString()"可以省略不写

2.1.2 equals方法

  • 直接比较两个对象的地址是否相同完全可以用“==”替代equals
  • 默认是与另一个对象比较地址是否一样,让子类重写,以便比较2个子类对象的内容是否相同
  • 父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则

2.2 Objects

  • 官方在进行字符串比较时,没有用字符串对象的的equals方法,而是选择了Objects的equals方法来比较,使用Objects的equals方法在进行对象的比较会更安全
  • 常用方法

2.3 String Builder

  • StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器
  • 作用:支持链式编程,提高字符串的操作效率,如拼接、修改等,性能较高
//链式编程
sb1.append("a").append("b").append("c").append("我爱你中国");
sb1.reverse().append("110");

2.3.1 常用方法

方法名称

说明

public StringBuilder append(任意类型)

添加数据并返回StringBuilder对象本身

public StringBuilder reverse()

将对象的内容反转

public int length()

返回对象内容长度

public String toString()

通过toString()就可以实现把StringBuilder转换为String

2.3.2 StringBuilder高性能原理图:

2.3.3 String和StringBuilder总结比较

  • String :内容是不可变的、拼接字符串性能差
    StringBuilder:内容是可变的、拼接字符串性能好、代码优雅
  • 定义字符串使用String
    拼接、修改等操作字符串使用StringBuilder

2.4 Math

方法名

说明

public static int abs(int a)

获取参数绝对值

public static double ceil(double a)

向上取整

public static double floor(double a)

向下取整

public static int round(float a)

四舍五入

public static int max(int a,int b)

获取两个int值中的较大值

public static double pow(double a,double b)

返回a的b次幂的值

public static double random()

返回值为double的随机值,范围[0.0,1.0)

2.5 System

方法名

说明

public static void exit(int status)

终止当前运行的 Java 虚拟机,非零表示异常终止

public static long currentTimeMillis()

返回当前系统的时间毫秒值形式

public static void arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数)

数组拷贝

2.6 BigDecima

  • 用于解决浮点型运算精度失真的问题
public static BigDecimal valueOf(double val):   包装浮点数成为BigDecimal对象。

方法名

说明

public BigDecimal add(BigDecimal b)

加法

public BigDecimal subtract(BigDecimal b)

减法

public BigDecimal multiply(BigDecimal b)

乘法

public BigDecimal divide(BigDecimal b)

除法

public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式)

除法

日期类、包装类、正则表达式、Arrays类、Lambda表达式

1 日期类

1.1 Date

  • 创建日期类,获取时间毫秒值
  1. public  Date();
  2. public long getTime();
  • 时间毫秒值恢复成日期对象
  1. public Date(long time);
  2. public void setTime(long time);

1.2 SimpleDateFormat

  • 完成Date日期对象,时间毫秒值的格式化操作
  1. public final String format(Date date)
  2. public final String format(Object time)
  • 进行字符串时间的解析
  1. public Date parse(String source)

1.3 Calendar日历

  • Calendar代表了系统此刻日期对应的日历对象
  • Calendar是一个抽象类,不能直接创建对象,需调用方法创建对象:
public static Calendar getInstance()
  • 常用方法

方法名

说明

public int get(int field)

取日期中的某个字段信息。

public void set(int field,int value)

修改日历的某个字段信息。

public void add(int field,int amount)

为某个字段增加/减少指定的值

public final Date getTime()

拿到此刻日期对象。

public long getTimeInMillis()

拿到此刻时间毫秒值

  • calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化

1.4 JDK8新增的日期类

2 包装类

2.1 包装类的概念和作用

  • 包装类是8种基本数据类型对应的引用类型,使用引用类型将基本数据类型对象化(一切皆对象),同时集合泛型其实也只能支持包装类型,不支持基本数据类型。

基本数据类型

引用数据类型

byte

Byte

short

Short

int

Integer

long

Long

char

Character

float

Float

double

Double

boolean

Boolean

2.2 自动装箱和自动拆箱

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

2.3 包装类特点

  • 包装类的变量的默认值可以是null,容错率更高
  • 可以把字符串类型的数值转换成真实的数据类型(很有用):
Integer.parseInt(“字符串类型的整数”)
Double.parseDouble(“字符串类型的小数”)

3 正则表达式

  • 用一些规定的字符来制定规则,并用来校验数据格式的合法性

3.1 正则表达式匹配规则

  • 在API文档Pattern类中查看
  • 字符类(默认匹配一个字符)
[abc]	       只能是a, b, 或c
[^abc]	       除了a, b, c之外的任何字符
[a-zA-Z]               a到z A到Z,包括(范围)
[a-d[m-p]]	       a到d,或m通过p:([a-dm-p]联合)
[a-z&&[def]]	       d, e, 或f(交集)
[a-z&&[^bc]]	       a到z,除了b和c:([ad-z]减法)
[a-z&&[^m-p]]     a到z,除了m到p:([a-lq-z]减法)
  • 预定义的字符类(默认匹配一个字符)
.	任何字符
\d	一个数字: [0-9]
\D	非数字: [^0-9]
\s	一个空白字符: [ \t\n\x0B\f\r]
\S	非空白字符: [^\s]
\w	[a-zA-Z_0-9] 英文、数字、下划线
\W	 [^\w] 一个非单词字符
  • 贪婪的量词(配合匹配多个字符)
X?	X , 一次或根本不
X*	X,零次或多次
X+	X , 一次或多次
X {n}	X,正好n次
X {n, }	X,至少n次
X {n,m}	X,至少n但不超过m次

3.2 提供的匹配方法

public boolean matches (String regex): 判断是否匹配正则表达式,匹配返回true,不匹配返回false。

3.3 正则表达式的应用

  • 表单验证
  • 在字符串方法中的使用(了解):
  1. public String replaceAll(String regex,String newStr)  按照正则表达式匹配的内容进行替换
  2. public String[] split(String regex) 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组
  • 爬取信息

4 Arrays

  • 数组操作工具类,专门用于操作数组元素
  • 常用方法:

方法名

说明

public static String toString(类型[] a)

返回数组的内容(字符串形式)

public static void sort(类型[] a)

对数组进行默认升序排序

public static  void sort(类型[] a, Comparator<? super T> c)

使用比较器对象自定义排序

public static int binarySearch(int[] a, int key)

二分搜索数组中的数据,存在返回索引,不存在返回-1

  • Arrays支持设置Comparator接口对应的比较器对象,来定制自定义比较规则(重要)

5 Lambda表达式(重要)

5.1 Lambda表达式的作用和格式

  • JDK 8开始后的一种新语法形式,用于简化匿名内部类的代码写法
  • 简化格式:
(匿名内部类被重写方法的形参列表) -> {
	被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义
    • Lambda表达式只能简化函数式接口的匿名内部类的写法形式
  • 函数式接口:首先必须是接口、其次接口中有且仅有一个抽象方法的形式
@FunctionalInterface // 一旦加上这个注解必须是函数式接口,里面只能有一个抽象方法

5.2 Lambda表达式的省略规则

  • 参数类型可以省略不写。
  • 如果只有一个参数,参数类型可以省略,同时()也可以省略。
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
  • 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
      Arrays.sort(ages1, new Comparator<Integer>() {
           @Override
           public int compare(Integer o1, Integer o2) {
               return o2 - o1; //  降序
           }
      });//简化前
	Arrays.sort(ages1, ( o1,  o2 ) ->  o2 - o1 );//简化后

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值