多态
- 同类型对象,执行同一个行为,会表现出不同的特征
多态成员访问特点:
- 方法调用:编译看左边,运行看右边
- 变量调用:编译看左边,运行也看左边(多态侧重行为多态)
public abstract class Animal {
public String name="动物名";
public abstract void run();
}
public class Dog extends Animal{
public String name="狗类名";
@Override
public void run() {
System.out.println("狗跑得快");
}
}
public class Tortoise extends Animal{
public String name="乌龟类名";
@Override
public void run() {
System.out.println("乌龟跑得慢");
}
}
public class test {
public static void main(String[] args) {
//1.多态形式: 父类名 对象名称= new 子类构造器
Animal a1=new Dog();
a1.run(); //编译看左(Animal中的run()),运行看右(执行Dog中的run())
System.out.println(a1.name); //输出:动物名,编译看左边,运行也看左边
Animal a2=new Tortoise();
a2.run();
System.out.println(a2.name);
}
}
优势
- 在多态形势下,右边对象可以实现解耦合,便于扩展和维护
- 定义方法时,使用父类型作为参数,该方法可以接受此父类的一切子对象,体现出多态的扩展性与便利
/**
* 所有动物都能进来比赛
*/
public static void comptetion(Animal a){
System.out.println(a.name+"加入比赛");
}
Animal a1=new Dog();
a1.run();
问题
- 多态下不能使用子类的独有功能
类型转换
public class test {
public static void main(String[] args) {
//1.自动类型转换
Animal a=new Dog();
a.run();
//2.强制类型转换,转换为真正的子类,调用子类的独有功能
Animal a2=new Tortoise();
Tortoise t= (Tortoise) a2; //从父类到子类,必须强制类型转换
t.layeggs();
//Dog d= (Dog) a2; //强制转换类型,编译阶段不报错(注意:有继承或实现关系,编译阶段可以强制,但是运行会报错)
if(a2 instanceof Tortoise){//判断要被强制转换的a2是否是Tortoise类
Tortoise t2= (Tortoise) a2;
t.layeggs();
}else{
Dog d2= (Dog) a2;
d2.lookdoor();
}
}
}
练习案例
/**
* USB接口==规范
*/
public interface USB {
//接入、拔出
void connect();
void unconnect();
}
public class keyboard implements USB{
private String name;
public keyboard(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 键盘独有功能
*/
public void keyDown(){
System.out.println(name+"键入信息操作");
}
@Override
public void connect() {
System.out.println(name+"成功接入电脑");
}
@Override
public void unconnect() {
System.out.println(name+"成功从电脑中拔出");
}
}
public class mouse implements USB{
private String name;
public mouse(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 鼠标独有功能
*/
public void dbClick(){
System.out.println(name+"双击操作");
}
@Override
public void connect() {
}
@Override
public void unconnect() {
}
}
public class computer {
private String name;
public computer(){
}
public computer(String name) {
this.name = name;
}
/**
* 安装USB设备
*/
public void installUSB(USB usb){
//多态:usb可能是keyboard,或是mouse
usb.connect(); //方法调用,编译看左边,运行看右边
//子类独有的方法的调用
if(usb instanceof keyboard){
keyboard k= (keyboard) usb;
k.keyDown();
}else{
mouse m= (mouse) usb;
m.dbClick();
}
usb.unconnect();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class test {
public static void main(String[] args) {
computer c=new computer("外星人");
USB k=new keyboard("键盘");
USB m=new mouse("鼠标");
c.installUSB(k);
c.installUSB(m);
}
}
内部类
-
静态内部类(了解)
/** * 外部类 */ public class outer { /** * 静态内部类 */ public static class inner{ private int age; public static String schoolName; public inner(int age) { this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static String getSchoolName() { return schoolName; } public static void setSchoolName(String schoolName) { inner.schoolName = schoolName; } } }
public class test { public static void main(String[] args) { //内部类创建对象 outer.inner in1=new outer.inner(12); } }
静态内部类能否直接访问外部类的静态成员?
- 可以,外部类的静态成员只有一份,可被共享访问
静态内部类能否直接访问外部类的实例成员?
不可以,外部类的实例成员,只能由外部类的对象访问
2.成员内部类(了解)
无static修饰,属于外部类的对象
/**
* 外部类
*/
public class outer {
/**
* 成员内部类
*/
public class inner2{
//JDK16开始支持静态成员和方法
}
}
public class test {
public static void main(String[] args) {
//成员内部类创建对象
outer.inner2 in2=new outer().new inner2();
}
}
成员内部类能否访问外部类的静态成员?
可以,外部类静态成员只有一份,可以共享
成员内部类能否访问外部类的实例成员?
可以,先有外部类对象,才有内部类对象,所以可以直接访问外部类对象的实例成员
面试题练习
class people{
private int hearbeats=150;
public class heart{
private int heartbeats=110;
public void show(){
int heartbeats=78;
System.out.println(heartbeats);//78
System.out.println(this.heartbeats);//110 访问当前类中的数据成员this.heartbeats
System.out.println(people.this.hearbeats);//150 访问外部类中的数据成员people.this.hearbeats
}
}
}
3.局部内部类(了解,基本不用)
4.匿名内部类(重点)
- 没有名字的局部内部类,定义在方法中、代码块中等
- 作用:方便创建子类对象,最终目的是简化代码编写
public class test {
public static void main(String[] args) {
//匿名内部类
Animal a=new Animal() {
@Override
public void run() {
System.out.println("狗跑得快");
}
};
a.run();
}
}
/*class dog extends Animal{
@Override
public void run() {
System.out.println("狗跑得快");
}
}*/
abstract class Animal{
public abstract void run();
}
特点
- 没有名字的内部类
- 写出来就产生一个匿名内部类对象
- 相当于当前new的类型的子类
作用:可作为方法的实际参数传输
public class test2 {
public static void main(String[] args) {
//学生类进行比赛
swimming s=new swimming() {
@Override
public void swim() {
System.out.println("学生自由泳");
}
};
competion(s);
System.out.println("======================");
//老师类进行比赛
competion(new swimming() {
@Override
public void swim() {
System.out.println("老师自由泳");
}
});
}
public static void competion(swimming s){
System.out.println("开始");
s.swim();
System.out.println("结束");
}
}
interface swimming{
void swim();
}
常用API
1.Object
作用
- 默认打印当前对象的地址
- 让子类重写,以便返回子类对象内容
//学生类中对toString重写
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
", age=" + age +
'}';
}
public class test {
public static void main(String[] args) {
Student s1=new Student("张三","110",22);
System.out.println(s1.toString());//返回对象地址,toString可省略
System.out.println(s1);
//重写后返回:Student{name='张三', id='110', age=22}
}
}
作用:
- 默认与另一个对象比较地址是否相同
- 让子类重写,以便比较两个子类对象内容是否相同
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name)
&& Objects.equals(id, student.id);
}
public class test {
public static void main(String[] args) {
Student s2=new Student("张三","110",24);
Student s3=new Student("张三","110",24);
//重写前
System.out.println(s2.equals(s3));
System.out.println(s2==s3); //false,默认比较两对象的地址
//重写后
System.out.println(s2.equals(s3));//true
}
}
2.Objects
Objects.equals(s1,s2)
public class test {
public static void main(String[] args) {
String s1=null;
String s2="1011";
//System.out.println(s1.equals(s2)); //报错,s1为null
System.out.println(Objects.equals(s1,s2)); //false,Objects.equals(s1,s2)更安全
System.out.println(Objects.isNull(s1)); //true
System.out.println(s1==null); //true
System.out.println(Objects.isNull(s2)); //false
System.out.println(s2==null); //false
}
}
3.StringBuilder
public class test {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder();
sb.append("A");
sb.append(true);
sb.append(100);
sb.append('a');
System.out.println(sb);//Atrue100a
//支持链式编程
StringBuilder sb1=new StringBuilder();
sb1.append(1).append("hello").append(false);
System.out.println(sb1);//1hellofalse
//反转
sb1.reverse().append(114514);//eslafolleh1114514
System.out.println(sb1);
//注意:StringBuilder只是拼接字符的手段,效率好
//最终结果还是要恢复成String类型
String rs=sb1.toString();
print(rs);
}
public static void print(String s){
System.out.println(s);
}
}
4.Math
5.System
public class test3 {
public static void main(String[] args) {
int[] arr1={10,20,30,40,50,60};
int[] arr2=new int[7];
System.arraycopy(arr1,3,arr2,1,2);
System.out.println(Arrays.toString(arr2));//[0, 40, 50, 0, 0, 0, 0]
}
}
6.BigDecimal
- 解决浮点型运算精度失真的问题
public class test {
public static void main(String[] args) {
double a=0.1;
double b=0.2;
double c=a+b;
System.out.println(c);//0.30000000000000004精度失真
//BigDecimal
BigDecimal a1=BigDecimal.valueOf(a);
BigDecimal b1=BigDecimal.valueOf(b);
BigDecimal c1=a1.add(b1);
//大数类型是运算手段,最终结果转回double
double d=c1.doubleValue();
System.out.println(d);//0.3
//注意:BigDecimal是一定要精度运算的
BigDecimal aa1=BigDecimal.valueOf(10.0);
BigDecimal bb1=BigDecimal.valueOf(3.0);
//BigDecimal cc1=aa1.divide(bb1); //报错,无限循环小数
/**
* 参数一:除数 参数二:保留小数位 参数三:舍入模式
*/
BigDecimal cc1=aa1.divide(bb1, 2,BigDecimal.ROUND_HALF_UP);
System.out.println(cc1.doubleValue());//3.33
}
}
标签:name,Day7,void,System,多态,mt,println,public,out
From: https://www.cnblogs.com/mt-nika/p/17064625.html