什么是多态?
同类型的对象,执行同一个行为,会表现出不同的行为特征
多态的常见形式
父类类型 对象名称=new 子类构造器
接口 对象名称=new 实现类构造器
多态成员访问特点
方法调用:编译看左边,运行看右边
变量调用:编译看左边,运行看右边(多态侧重行为多态)
多态的前提
有继承/实现关系;有父类引用指向子类对象,有方法重写
多态的优势:
优势:在多态形式下,右边对象可以实现解耦合,便于扩展和维护
定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利
多态下会产生的一个问题:
多态下不能使用子类的独有功能
自动类型转换(从子到父):子类对象赋值给父类类型的变量指向
强制类型转换(从父到子):必须进行强制类型转换:子类 对象变量=(子类)父类类型的变量
作用:可以解决多态下的劣势,可以实现调用子类独有的功能
注意:如果转型后的类型和对象真实类型不是同意中类型,那么在转换的时候就会出现ClassCastException
java建议强制转换前使用instanceof判断当前对象的真实类型,再进行强制转换
变量名 instanceof 真实类型
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之
内部类:
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)
内部类的使用场景、作用
当一个食物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又职位外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计
内部类通常可以方便访问外部类的成员,包括私有的成员
内部类提供了更好的封装性,内部类本身就可以用private protected等修饰,封装性可以做更多控制
静态内部类
什么是静态内部类?有static修饰,属于外部类本身
他的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已
public class Outer{
//静态成员内部类
public static class Inner{
}
}
静态内部类创建对象的格式:
格式:外部类名.内部类名 对象名=new 外部类名.内部类构造器;
范例:Outer.Inner in=new Outer.Inner();
成员内部类
匿名内部类:
本质上是一个没有名字的局部内部类,定义在方法中,代码块中
作用:方便创建子类对象,最终目的为了简化代码编写
格式:
Employee a=new Employee(){
public void work(){
}
}
a.work;
特点总结:
匿名内部类是一个没有名字的内部类
匿名内部类写出来就会产生一个匿名内部类对象
匿名内部类的对象类型相当于是当前new的那个类型的子类类型
匿名内部类的作用?
方便创建子类对象,最终目标为了简化代码编写
package d6_innerclass_anonymous; public class Test2 { public static void main(String[] args) { Swimming s=new Swimming() { @Override public void swim() { System.out.println("学生快乐的自由泳"); } }; go(s); } //学生 老师 运动元可以一起参加比赛 public static void go(Swimming s){ System.out.println("开始"); s.swim(); System.out.println("结束"); } } class Student implements Swimming{ @Override public void swim() { System.out.println("学生快乐的自由泳"); } } interface Swimming{ void swim(); };
匿名内部类在开发中的真实使用场景:
给按钮绑定点击事件
Object类的作用:
一个类要么默认继承了Object类,要么间接继承了Object类,Object类是java中的祖宗类
Object类的方法是一切子类都可以直接使用的,所以我们要学习Object类的方法
Object类的常用方法:
public String toString() 默认是返回当前对象在堆内存中的地址信息:类的权限名@内存地址
public Boolean equals(object o):默认是比较当前对象与另一个对象的地址是否相同,相同则返回true,不同返回false
问题引出:
开发中直接输出对象,默认输出对象的地址其实都是毫无意义的
开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息
toString存在的意义
父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!
可以快捷键生成
Object的toString方法的作用是什么?
默认是打印当前对象的地址
让子类重写,以便返回子类对象的内容
Object的equlas方法:
public Boolean equals(Object o) 默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false
直接比较两个对象的地址是否相同完全可以用==替代equals
想要比较内容就需要重写一个equals方法
@Override public boolean equals(Object o) { //判断是否是同一个对象比较,如果是返回true if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Studet studet = (Studet) o; return sex == studet.sex && age == studet.age && Objects.equals(name, studet.name); }
object的equals方法的作用是什么?
默认是与另一个对象比较地址是否一样
让子类重写,以便比较2个子类对象的内容是否相同
Objects
Objects类与Object还是继承关系,Objects类才是JDK1.7开始之后才有的
官方在进行字符串比较时,没有对象自己的equals方法,而是选择了Objects的equals方法来比较两个对象
Objects的equals方法比较的结果是一样的,但是更安全,不会出现空指针异常
Objects的常见方法
public static boolean equlas(Object a,Object b) 比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常。再进行equals比较
public static boolean isNull(Object obj) 判断变量是否为null,为null返回true,反之false
源码分析:
public static boolean equlas(Object a,Object b){
return (a==b)||(a!=null&&a.equlas(b));
}
Objects.isNull(对象名);
对象进行内容比较的时候建议使用什么?为什么?
建议使用Objects提供的equals方法
比较的结果是一样的,但是更安全
StringBuilder概述:
StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器
作用:提高字符串的操作效率,如拼接,修改等
StringBuilder构造器
public StringBuilder() 创建一个空白的字符串对象,不包含任何内容
public StringBuilder(String str) 创建一个指定字符串内容的可变字符串对象
String类拼接字符串原理图
解析:创建s1时,字符串常量池中添加"a"
创建s2时,字符串常量池中添加"b",并且在堆内存中创建一个对象,new StringBuilder(),在 通过toString添加到String中
StringBuilder内存图
为什么拼接、反转字符串建议使用StringBuilder?
String:内容是不可变的,拼接字符串性能
StringBuilder:内容是可变的,拼接字符串性能好,代码优雅
定义字符串使用String
拼接、修改等操作字符串使用StringBuilder
package d11_api_stringbuilder; public class StringBuilderDemo2 { public static void main(String[] args) { int[] arr1=null; System.out.println(arr1); int[] arr2={10,28,39,76}; System.out.println(toString(arr2)); } /*1.定义方法接受任意整形数组,返回数组内容格式*/ public static String toString(int[] arr){ if(arr!=null){ //2.开始拼接内容 StringBuilder sb = new StringBuilder("["); for (int i = 0; i < arr.length; i++) { sb.append(arr[i]).append(i==arr.length-1?"":","); } sb.append("]"); return sb.toString(); }else{ return null; } } }
Math类
包含执行基本数字运算的方法,Math类没有提供公开的构造器
如何使用类中的成员呢?看类的成员是否都是静态的,如果是,通过类名就可以直接调用
package d11_api_stringbuilder; public class StringBuilderDemo3 { public static void main(String[] args) { //1.取绝对值:返回正数 System.out.println(Math.abs(-10.7));//10 //2.向上取整:5 System.out.println(Math.ceil(4.000007));//5 //3.向下取整:4 System.out.println(Math.floor(4.99999));//4 //4.求指数数次方 System.out.println(Math.pow(2.3,4.6)); //5.四舍五入 System.out.println(Math.round(4.499999)); System.out.println(Math.round(4.500001)); //四舍五入 System.out.println(Math.random()); } }
System类概述:
System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化
Syste,类的常用方法
public static void exit(int status) 终止当前运行的Java虚拟机,非零表示异常终止
public static long currentTimeMillis() 返回当前系统的时间毫秒值形式
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数) 数组拷贝
import java.util.Arrays; public class d12_system { public static void main(String[] args) { System.out.println("程序开始"); //System.exit(0); //1.计算机认为时间有起源: long time = System.currentTimeMillis(); System.out.println(time); long startTime = System.currentTimeMillis(); //进行时间的计算。性能分割 for (int i = 0; i < 10000; i++) { System.out.println("输出..."+i); } long endTime = System.currentTimeMillis(); System.out.println((endTime-startTime)/1000.0+"s"); /*arraycopy(Object src,int srcpas * ,Object dest,int desPas,int length) * */ int[] arr1={10,20,30,40,50,60}; int[] arr2=new int[arr1.length]; System.arraycopy(arr1,3,arr2,2,3); System.out.println(Arrays.toString(arr2)); System.out.println("程序结束..."); } }
BigDecimal作用
用于解决浮点型运算精度失真的问题
创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
public static BigDecimal valueOf(double val):包装浮点数成为BigDecimal对象
BigDecimal的作用是什么?
解决浮点型运算精度失真问题
BigDecimal的对象如何获取?
BigDecimal b1=BigDecimal.valueOf(0.1);
BigDecimal必须解决精度运算,如果进行10/3的运算,会报错,需要做取整 操作