• java学习笔记(Core Java)5 继承


    第五章 继承

    1. 类 超类 子类
    继承:extends (所有继承嗾使公有继承,没有私有继承和保护继承)
    c+++: 用:

    2.使用super(c#使用Base)调用基类的方法
    子类构造器会默认调用基类的无参构造来初始化基类的私有域
    如果基类没有无参构造,则会报错

    3.this :1.引用隐式传参 2.调用类其他构造器
    super:1.调用超类的方法 2.调用超类的构造器

    c++使用初始化列表来调用基类的构造函数

    4.java中,不需要将方法声明为虚拟方法方法,基类指针指向不同对象时,虚拟指针知道指针指向的实际对象类型,所以能正确调用对应的方法

    如果不希望让一个方法具有虚拟特征,可以标记为final

    5.java不支持多继承
    6.多态:动态绑定、静态绑定和方法表
    1)编译器准确知道调用哪个方法的叫静态绑定
    (用private、static、final声明过的方法)
    在运行时,调用方法依赖于实际类型并实现方法绑定(运行时可知)的叫动态绑定

    虚拟机为基类和派生类生成一个方法表,虚拟机会在方法表中搜索最适合的方法进行调用

    动态绑定的优点就是:对程序进行拓展时,不需要重新对调用方法的代码进行重新编译

    方法重写时,子类的方法的访问性不能低于基类方法

    7.阻止继承 final类
    final修饰的类不能被继承
    final修饰的方法不能被覆盖
    final修饰的域在构造方法内初始化,并且不能被改动

    被final修饰的类,其方法自动为final方法,但而不包括域

    动态绑定对系统开销很大,所以即时编译器会自动为没有被覆盖的类标记为内联函数,减少对系统的开销

    8.强制转换
    1)只能在继承层次内进行转换
    2)将基类转换为子类之后,需判断是否转换成功 使用instanceof运算符算符检查
    Employee[] staff = new Employee[3];
    java:Manager boss = (Manager)staff[1];
    if(staff[1] instanceof Manager)//instanceof实例是否属于该类
    ...
    c++: Manager* boss= dynamic_cast<Manager*>(staff[1])
    if(boss!= null)
    ...

    如果转换失败java不会生成一个空对象,而是抛出一个异常

    补充: c++四种强制类型转换,所以c++不是类型安全的
    static_cast:基本数据类型转换
    const_cast:常量转化为非常量,或者反过来
    reinterpret_cast:任意类型转换而无须考虑安全和常量问题,不要轻易使用
    dynamic_cast:运行时转换,运行时要进行类型检查,存在继承关系之间(类中要有虚函数才能进行此转换,需检查类型信息,而类型信息保存在虚函数表中)
    9.抽象类与抽象方法
    抽象类包含抽象方法也可以包含具体数据、具体方法
    类即时不含有抽象方法,也可以声明为抽象类
    抽象类不能被实例化

    c++:尾部=0的方法为纯虚函数,包含虚函数的类为虚类(抽象类) (虚函数可以有自己的实现,纯虚函数=0)

    10.访问权限:
    private:本类可见(也是c++初始化列表的原因,因为子类不可方位基类的private字段,需要调用基类的构造函数)

    public:对所有类可见
    protected:本包和所有子类可见(c++只对子类可见)
    默认(无修饰符):对本包可见

    11.object 超类
    在java中,只有基本类型不是对象,其他类型(包括数组,枚举)都是对象,都扩展于超类

    c++:void* ,每个指针都可以转化为void*指针

    12.equal 仅比较了是否具有相同的引用
    最好手动的重写equal方法

    重写equals方法的要求:
    1.自反性:对于任何非空引用x,x.equals(x)应该返回true
    2.对称性:对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。
    3.传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
    4.一致性:如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回同样的结果。
    5.非空性:对于任意非空引用x,x.equals(null)应该返回false。

    重写equals方法的要点:(注意! 重写该方法)
    @overrade public boolean equal(OBject otherObject)
    1. 使用==操作符检查“实参是否为指向对象的同一个引用”。
    if(this == otherObject)
    2.判断实参是否为null
    if(otherObject == null)
    3. 使用instanceof操作符检查“实参是否来自是否同一个类”。
    if(getClass()!= otherObject.getClass()) //是否同一个类
    if(!(otherObject)instanceof ClassName)//如果所有子类拥有统一的语义
    4. 把实参转换到正确的类型。
    ClassName other = (ClassName)otherObject

    5.对所有域依次比较:对于该类中每一个“关键”域,检查实参中的域与当前对象中对应的域值是否匹配。对于既不是float也不是double类型的基本类型的域,可以使用==操作符进行比较;对于对象引用类型的域,可以递归地调用所引用的对象的equals方法;对于float类型的域,先使用Float.floatToIntBits转换成int类型的值,然后使用==操作符比较int类型的值;对于double类型的域,先使用 Double.doubleToLongBits转换成long类型的值,然后使用==操作符比较long类型的值。

    6.当你编写完成了equals方法之后,应该问自己三个问题:它是否是对称的、传递的、一致的?(其他两个特性通常会自行满足)如果答案是否定的,那么请找到这些特性未能满足的原因,再修改equals方法的代码。

    数组可以使用Arrays.equal来判断
    ////////////////////////////
    java.util.Arrays
    static Boolean equal(type[] a,type[] b);
    static Boolean equal(object a,object b);
    ////////////////////////////

    13.hashCode
    每个类都有一个散列码
    如果重写equal,也需要重写hashCode

    14.toString 强烈建议自己的类重写提String方法,用于打印日志或者错误信息 例如:
    public String toString()
    {
    return getClass().getClass
    + "[name=" + name
    + "age=" + age
    + "]";
    }

    println会直接调用x.toString方法

    数组需要调用Arrays.toString方法
    多维数组调用Arrays.deepString方法

    /////////////////////////
    java.lang.Object
    Calss getClass() //返回包含对象信息的类对象
    boolean equal()
    String toString();

    java.lang.Class
    String getName();
    Class getSuperclass() //返回超类信息
    /////////////////////////

    15.泛型数组 ArrayList<T> array = new ArrayList<T>()
    1)c++:类似于vector,但是没有重载[]。再c++中,列表a=b时一种值拷贝,而在java中,a=b则a,b指向同一个列表

    (1)add()
    add(int index, T obj) //需要移动大量元素
    (2)ensureCapacity(100) //如果可以估计存储数量,可以再填充前分配一个这么大的内部//数组空间
    (3)size == 数组a.length()
    (4)trimToSize() //如果确认列表大小不再增大,可以调用该方法清除多余的空间

    5)set/get :由于没有重载[]运算符。。。。
    set(int iT obj);//替换某个位置上的某个值(不是增加!)
    T get(int i); //返回object,获取后需要强制转换
    6)T remove(int index) //需要移动大量元素
    7) x [] = new x[list.size()]
    list.toArray(x) //导入数组
    历史遗留问题:
    ArrayList list=employee.find(oldlist)//参数列表元素可能有些不相符
    由于早期ArrayList没有泛型,所以将一个原始的ArrayList赋值一个类型化的ArrayList会有警告,只要确保不会造成后果,可以使用@SuppressWarning("unchecked"),关闭此条警告

    16拆箱与装箱
    每个基本类型都有之对应的类(对象包装类)
    Integer Long Float Double Short Byte Character Void Boolean(前六种继承Number类)

    对象包装类不允许修改其中的值,同时也是final声明的
    使用包装器声明变量时,其==表示其是否指向同一个对象,因此
    两个对象包装器比较时调用equal方法

    17.java如何改变传参的值??
    C++:指针传参,引用传参 c#:使用 ref 标记实参与形参
    java 使用持有者类型(IntHolder、BooleanHold等)
    public static void triple(IntHolder x)
    {
    x.value = 3 * x.value; //可以改变传参的值
    }

    关于c++引用:
    引用其实就是一个常量指针,同时也是用常量指针去实现的。引用占用四个字节。因为是常量指针,所以不能修改被引用的对象的内容。这比使用指针将更加安全

    /////////////////////////////
    java.lang.Integer
    int intValue();//返回interger中的值
    static String toString(int i);//将int包装为十进制String
    static String toString(int i,int radix);//指定进制
    static int parseInt(String s) //c# int.prase(String s)
    static int parseInt(String s,int radix)
    static Integer valueOf(String s)
    static Integer valueOf(String s,int radix)

    java.text.Number.Format
    Number prase(String s); //假设s时一个数值
    /////////////////////////////

    18.可变参数 使用...
    public static double max(double... value);
    实际上将若干参数绑定在数组中传递该max函数
    public static void main(String... args);

    19.枚举 enum
    实际上是一个类,包含若干个实例,因此两个枚举类型的值比较,直接使用 == ,永远不要调用equal。
    所有的枚举类型都是Enum类的子类。所以他们继承了这个类的许多方法String toString() //返回枚举常量名
    static Enum valueOf(Class enumClass,String name)//返回指定名字给定类的枚举常量
    int ordinal() //返回在enum声明中枚举常量的索引 (从0 开始)
    int compareTo(E other) //在枚举中的顺序比较

    20反射与反射库
    反射被大量用在javaBeans中。
    反射的作用:
    ①在运行中分析类的能力
    ②在运行在查看类的对象
    ③实现通过的数组操作代码
    ④利用Method对象。 特别C++像函数指针(C#,委托与事件)
    极其强大的构造工具!!!

    (1)Class类
    程序运行时,java运行系统始终为所有的对象维护一个被称为运行时的类型标识,这个信息跟踪着每个对象所属的类,虚拟机会利用运行时的类型信息选择相应的方法执行.Class类负责维护这些信息,每一个java类在虚拟机种都会表现出一个Class类 (这与Object中的getClass 返回类的实例容易混肴)

    Employee e;
    e.getName();//返回一个Class对象

    e.getClass().getName();//返回类的名字

    如果类在包里,在返回 包名+实例名
    Data d = new Data();
    Class c = d.getClass();
    String name = c.getName(); // java.util.Data

    使用静态方法forName获取类名对应的Class对象
    String classname = "java.util.Data";
    Class c = forName(classname);//该方法只有在classname时类名或者接口名中使用,否则会抛出异常 checked exception.使用该方法需要提供一个异常处理器

    (可以先启动程序,然后使用forName加载所有的类,给用户一种启动很快的幻觉)

    使用T.class方法获取匹配的类对象(T代表任意java类型)
    Class c1 = Data.class
    Class c2 = int.class
    Class c3 = double[].class//历史原因,数组会返回一个比较奇怪的类名

    总结:
    三种方法获取Class类对象
    实例名.getClass
    任意类型T.class
    forName(类名字符串)//这是一个静态方法 Class.forName(s);

    Class Poin(){...}
    Point p = new Point();
    Class c1 = p.getClaa();
    System.out.println(c1.getName()) // Point

    Class c2 = Class.forName("Point")
    System.out.println(c2.getName()) // Point

    Class c3 = Point.class;
    System.out.println(c3.getName()) // Point

    每一个类的对象在虚拟机中都会生成一个Class类对象来保存这个每个类的信息,可以获取到这些信息进而获取到这个类的所有信息。
    虚拟机为每一个类型管理一个Class对象,
    可以用 == 比较两个类对象 if(e.getClass() == Employee.class) ...
    获取实例后也可以反射创建对象 e.getClass().newInstance();
    newInstance() 会调默认的构造方法,如果没有,将抛出异常

    forName与newInstance() 根据类名生成对象
    String s = "java.util,Data";
    Data d = (Data)Class.forName(s).newINstance();

    Constructor类中的newInstance()//提供构造器参数

    ////////////////////////////
    使用printStackTrace打印出栈的轨迹
    java.lang,Class
    static Class forName(String classname);
    Object newInstance();

    java.lang,reflect.Constructon
    Object newInstance(Object[] args);//带参构造
    ////////////////////////////

  • 相关阅读:
    TSQL入门(msdn)
    在代码中,获取Entity Framework生成的TSQL查询语句
    Code First(一)
    UDPClient的用法
    Building Applications that Can Talk(转)
    Asynchronous Web and Network Calls on the Client in WPF(摘录)
    DropBox能正常使用了
    显示GIF图标报错:“A generic error occurred in GDI+.”
    第 2 篇Scrum 冲刺博客
    第 1 篇 Scrum 冲刺博客
  • 原文地址:https://www.cnblogs.com/luckyQi/p/6782501.html
Copyright © 2020-2023  润新知