隐藏多态、抽象、接口、 Object、类与类的关系

成员变量是所有实例的变量,在对象调用完了后会恢复原来的赋值或初始值
静态变量是类的变量,在调用完成后会保持这个变化

因为用的是成员变量所以要用成员方法,不能用静态方法因为静态方法不能有成员变量(
静态上下文不能引用非静态变量,因为静态方法加载时成员变量还没加载)


多态缺点
丢失子类特有属性

public class Poly_03 {
public static void main(String[]args){
    sub a = new sub();
    //编译阶段,和对象没有关系,就算赋值为空都可以,顶多运行时才会出现空指针异常,但是是可以运行的
    //说明编译时检查语法结构的时候,和是哪个对象没有关系,就看类型
    sub a1 = null;
    System.out.println(a1.age);
    //同理,就算后面不是null,编译阶段也和它没关系,没运行还没有对象
    sup s = new sub();
    //目前编译器只知道对应的sup中没有age属性,所以编译时就报错了
    //所以 导致多态的缺点:丢失子类特有属性
    System.out.println(s.age);//age报错age cannot be resolved or is not a field
}
    }
class sub extends sup{
    int age=12;
}
class sup{    
}
==============
向下转型
    多态:又叫向上转型
          子类到父类  是向上
          父类到子类  是向下
          想要向下转型,必须先向上转型
          
    public static void main(String[] args) {
        Animal a = new Cat();
        // 强制类型转换为cat类型
        // Cat c = (Cat)a;
        // java.lang.ClassCastException: _10_Polymorphic.Cat cannot be cast to _10_Polymorphic.Dog
        // 强制转换 可能会出现类型转换异常
        // Dog d = (Dog) a;
        // instanceof : 判断某个对象是否由某个类实例化而来
        if (a instanceof Dog) {
            Dog d = (Dog) a;
            System.out.println("狗");
        }else if (a instanceof Cat) {
            Cat c1 = (Cat)a;
            System.out.println("猫");
        }
    }
} 

         
=====================
比较隐秘的多态

public class Poly_05 {

    public static void main(String[] args) {
                             Sub_04 sub = new Sub_04();
        sub.m1();
        System.out.println("main--"+sub);
    }
}
class Sup_04 {
    int i = 22;
    public void m1() {
        // this 保存的是子类的内存地址,因为用哪个对象调用的这个方法,this就指向谁
        // this 是对象中第一个成员变量,保存当前对象的内存地址
        // 既然是变量,肯定有类型,可以保存当前类对象的类型有 
        // 1 当前类类型(this所在的类就是当前类)
        // 2 父类类型(多态,缺点 : 丢失子类特有的属性)
        // 而 this 可以调用当前类中特有的属性,所以 this的类型 应该是当前类类型
        // this在哪个类,哪个类就是当前类,而现在这个程序 this在 Sup_04 类父类中
        // 所以 就等于是 Sup_04 this;
        // 而 谁调用的这个方法,this就指向谁,这个m1方法最终是由 new Sub_04() 调用的,所以 this指向 new Sub_04()
        // 相当于 : Sup_04 this = new Sub_04();
        // 总结 : 通过子类,调用父类的方法的时候,此时父类这个方法中的上下文环境,就是多态环境
        System.out.println("m1--"+this);
        System.out.println(this.i);
        m2();
    }

    public void m2() {
        System.out.println("父类的m2方法");
    }
}

class Sub_04 extends Sup_04 {
    int i = 33;

    public void m2() {
        Sup_04    x = new Sub_04();
        System.out.println("子类的m2方法");
    }
}


====================
抽象 : 抽象类往往表示设计中得出的抽象概念
       比如人类,它只是一个抽象的概念,没有一个具体的东西叫动物,所以它不能代表一个实体
       这种情况下 适合把它作为一个抽象类
abstract: 修饰符,修饰的类是抽象类,修饰的成员方法是抽象方法
抽象方法:使用abstract修饰的成员方法,并且该方法没有方法体
抽象类:不能被实例化,只能用于被继承       
    一般抽象类中,有功能的定义,但是没有功能的实现,要求必须让子类覆写
    继承这个抽象类后,必须要实现抽象类中所有抽象方法
    实现:子类对抽象方法加上方法体,完成功能实现
    含有抽象方法的类型一定是抽象类
    抽象类不一定含有抽象方法
    抽象类继承抽象类可以不实现父类抽象方法也可以实现
    抽象类和普通类不同点是他不能创建对象它可以有抽象方法
     abstract 和 final 不能同时出现
  
  abstract修饰的类 是抽象类,就是用来被继承的 而 final修饰的类 不能被继承
  
  abstract修饰的方法 是抽象方法,而抽象方法就是用来被覆写实现的, 而 final修饰的成员方法 不能被覆写
  
  

 public class Abstract_02 {
    static public  void main(String[] args) {

    }
}

// abstract final class A1 {
abstract class A1 {
    // public abstract final void m1();
    abstract public  void m1();
}
  

     
=======================================    
引用数据类型:类 接口 数组

    
接口 : 
  接口是一种引用数据类型,可以看作是一个特殊类,是为了解决Java中单继承功能变弱问题
  一个类只能继承一个父类,但可以实现N个接口
  
  1  [修饰符] interface 接口名{}
  2   1.8之前 接口中只有抽象方法和常量(public static final)
         -2147483648~ 2147483647
  3接口中public static final  abstract 都可以省略(接口中没有变量,只有常量,写个方法就是抽象方法)
  4接口没有构造方法,不能创建对象
  5一个类要实现接口,需要实现所有抽象方法
  6一个抽象类实现一个接口需要实现0~n个抽象方法
  
  1.8以后可以有静态方法和默认方法1.9开始支持private方法
  -----------
 

public interface Interface_01 {
  public static final String A="xxx";//psf可以省略
  String B="yyy";
  public abstract void m1();
  //p a 都可省
  //静态方法1.8以后接口支持这俩方法
  public static void m3(){
      System.out.println("静态方法");
  }
  public default void m4(){
      System.out.println("默认方法");
  }
}
//implement 实现
class Sub implements Interface_01{
@Override
    public void m1() {
        // TODO Auto-generated method stub
}    
}


------------------------------

 public class Interface_02 {

}
interface A{//省略了p
    void m1();
}
interface B {
    void m2();
}
// 接口和接口之间是多继承 多个以逗号隔开
interface C extends A,B {
    void m3();
}
// 类和接口直间是多实现,保留类继承,所以 当抽象类和接口都能满足需求的时候,优先使用接口 
// 一个非抽象类实现接口后,需要实现所有抽象方法
// 一个抽象类实现接口后,需要实现0~N个抽象方法
class D extends Object  implements A,B{

    @Override
    public void m2() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void m1() {
        // TODO Auto-generated method stub
        }
    } 


------------------

public static void main(String[] args) {
        System.out.println(Interface_01.A);
        Interface_01.m3();

        // 接口不能创建对象
        // Interface_01 s = new Interface_01();
        Sub sub = new Sub();
        sub.m4();
        // 接口可以发生多态
        Interface_01 obj = new Sub();
    }


 
======================================
 Object,equals,toString, hashCode,finalize
 
 Object
 Object : 是Java提供的根类,所有类都需要直接或间接的继承Object
 Object中的方法,是所有类都有的
 Object xxx = new xxx()是可以发生多态的
 因为多态的原因,如果一个方法需要传递数据,并且无法确定数据的类型的时候就可以死用Object
  
  
  equals
  比较基本类型时比较的是值的大小,但是比较引用类型的时候比较的是内存地址
  而当我们需要比较两个对象的时候,往往需要根据对象的属性的值来进行比较,而不是比较他们是不是
  一个对象,因为这样没有任何价值
  此时==就不能解决我们的问题
  于是Object中提供了一个equals方法,专门用于比较两个对象是否相同,是否为同一个对象
  public boolean equals(Object obj){
        return this == obj;
  }
  关于Object中的equals方法
     设计目的:比较两个对象是否相等
     默认比较内存地址,需要根据需求进行重写
------------------------

public class Equala_01 {
    public static void main(String[] args) {
        Student s1 = new Student(101,"张三");
        Student s2 = new Student(101,"张三");
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));
    }
}
class Student{
    int no;
    String name;
    //需求:学号相同,姓名相同就是一个人
    @Override
    public boolean equals(Object obj) {
        if(this==obj){//如果内存地址相同,说明是同一个对象,直接返回真
            return true;
        }//判断是否是同类对象,不同类的对象没有可比性
        if(obj instanceof Student){//到这说明是Student的对象
            //由于发生了多态,object丢失了子类属性,所以要向下转型
            Student s = (Student)obj;
            //比较,引用类型最终都要转换为基本类型比较
            //String 类中重写了equals方法,底层是char数组,所以比较也是把数组中的char拿出来比较,还是基本类型
            if(this.no == s.no&&this.name.equals(s.name)){
                return true;
            }
        }
        return super.equals(obj);
    }
    public Student(int no, String name) {
        super();
        this.no = no;
        this.name = name;
    }    
} 

    
============================================ 
  toString
  设计目的 : 返回该对象的字符串表示形式
  输出一个引用类型时,默认输出内存地址
  当我们输出一个引用类型的时候,会自动调用该对象的toString 方法,默认的toString 方法,只返回内存地址
  比如我们需要打印一个对象的时候,展示出对象中的属性信息,就可以重写toString方法
  

 public class ToString_01 {
public static void main(String[]args){
    Person p1 = new Person("张三",18);
    System.out.println(p1);    
}
}
class Person{
    String name;
    int age;
    @Override
    public String toString() {
        return  "我是"+name+",今年"+age+"岁了";
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }    
}


==================================
 finallize
jvm四大特性:
多线程
面向对象
自动垃圾回收机制
跨平台
finallize是什么
   1 finalize每个对象都有
   2 不需要手动调用,系统自动调用
   3 垃圾:没有更多引用指向这个对象的时候,该对象被视为垃圾数据(创建
   了有一个对象,谁也没找到它),等待被回收
   4 当一个垃圾被回收之前,会自动调用该对象的finalize方法
   所以结合finalize的执行时机,适合做一个资源销毁操作
   只要是在对象回收前执行的事,都可以放在finalize中
   5 如果我们手动调用了finalize方法,那么它只是一个普通的方法,并不会被回收
 

 public static void main(String[] args) {
        Person1 person = new Person1();
        person = null;
        for (int i = 0; i < 100; i++) {
            // 程序员可以建议回收,但是它可以不接受建议
             System.gc();
//            new Person();
        }
    System.out.println(Finalize_01.person.age);
    }
    static Person1 person;
}

class Person1 {
    int age;
    @Override
    protected void finalize() throws Throwable {
        System.out.println(this + "我要被回收了");
        // 再重新指向该对象的时候,就会放弃回收
        Finalize_01.person  = this;
    }
}


   =====================
hashCode
   设计目的:为了给每个对象生成HASH值
   多个对象生成多次hash值,值一定相同,但是多个对象也可能生成相同的hash值,叫哈希冲突
   
类与类之间的关系
  1 继承  使用extends表示
类A extends 类B{}
接口A extends 接口B,接口C{}
类和类之间是单继承,接口和接口之间是多继承

2 实现 implements
类A implements 接口B,接口C
类和接口是多实现

3 依赖
某个类中的方法的局部变量,是另一个类的对象引用
这种关系是临时性的,方法执行结束,关系就不存在了

4 关联
某个类的成员变量是另一个类对象的引用
这种关系一般是长期的

5 聚合
整体和局部可以分离,各自具备独立的生命周期
比如公司和员工

假如A需要保存B的引用,这个引用一般是调用处传递过来的,这样的话 调用处和A 都保存B的引用,此时就算A销毁了,B也不会销毁,因为还有其他引用指向

6 组合
组合的关系要强于聚合,又叫强聚合
同样是整体和局部,但是不可分离,局部没有独立的生命周期
比如A保存B的引用,一般这个引用是A自己创建的,这样的话,A每创建一个对象,都需要创建一个B的对象,此时A销毁之后,B也就销毁了,因为没有其他指向了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值