【Java基础】03-类的重用

类的继承

Java会给每个对象分配非静态属性的内存,但是方法,无论是不是静态,都只在内存中存在一份。

Java中继承使用关键字extends。 Java中允许子类的属性和父类的同名,此时子类中包括两个重名的属性,即两个属性都存在于子类中。如果不加任何修饰,默认子类中访问的是子类定义的属性。如果想访问超类的属性,可以使用super关键字。

子类要覆盖超类的方法,必须将方法名、参数表、返回值和被覆盖的方法一模一样。覆盖方法的访问权限必须不能比被覆盖方法严格。如父类中一个方法的访问权限为protected,则子类中覆盖方法的访问权限必须是protected或者是public。

子类不能覆盖父类的final关键字或者static关键字修饰的方法。和属性的调用一样,可以使用super关键字访问父类的方法。

Object类

Object类是所有类的超类,定义了所有类都拥有的一些方法,如下:

  1. public final Class getClass();
  2. public String toString();
  3. public boolean equals(Object obj);
  4. protected Object clone();
  5. public int hashCode();
  6. public void finalize() throw Throwable
  • 实际上,equals() 判断两个对象的引用是否指向同一个对象,即两个对象是否是同一个对象。这一点和==运算符实现的是同一个功能。实际上,我们使用equals()方法有时事项比较两个对象是否是同一个类,且属性值相等。这才是真正意义上的“相等”,而不是“同一”。如字符串类就覆盖了equals()方法,返回的结果就是字符串的内容是否相等,而不是是否是同一个对象,我们可以自己覆盖equals(方法)来实现自己想要的功能。
  • toString()方法之前说过,返回 类名@对象的hashcode
  • hashCode()方法返回一个对象的散列码。Java语言规定两个引用指向同一个对象,则两个引用的hashCode()方法返回的散列码相同;但是不强制指向不同的对象,两个引用的散列码不同;且不要求两次代码执行的同一个引用的散列码相同。Java只规定了散列码这样的要求,没有规定具体的实现方法。
  • clone()方法返回一个克隆的对象。且覆盖clone方法的时候需要实现Cloneable接口。
  • finalize()方法在内存回收的时候自动调用,里面实现了垃圾回收的一些功能。当需要覆盖finalize()方法的时候,需要在方法的最后调用super.finalize(),以便实现完整的垃圾回收机制。
  • getClass()方法返回对象所属的类。getClass()方法是被final关键字修饰的,不能重写。可以试想通过Class对象查询类的各种信息。

Object中还定义了3个和线程相关的方法,且都是final方法,notify,notifyAll,wait。

final类和final方法

final类不能被继承;final方法不能被重写;final属性必须立即初始化,初始化以后不允许修改。

抽象方法

定义了抽象方法的类必须定义为抽象类,即方法被abstract关键字修饰,则类也必须被abstract关键字修饰。

抽象方法的声明:
[public] abstract (…);
抽象方法仅有方法原型,没有方法体。

泛型

Java中的泛型和C++中的模板类似,泛型方法在方法声明的时候传入类型参数,这样可以在编译时指定类型,从而使得程序更加通用且减小程序员的负担。一个典型的泛型类代码如下

class GeneralType <Type>{
    Type obj;
    public GeneralType(Type obj){this.obj = obj;}
    public Type getObj(){
        return obj;
    }
}

public class Test {
    public static void main(String[] args){
        GeneralType<Integer> t = new GeneralType<Integer>(2);
        GeneralType<Double> d = new GeneralType<Double>(4.3d);
        System.out.println(t.getObj());//2
        System.out.println((Double) d.getObj());//4.3
    }
}

其次,还可以在类中的方法前指定通配符,这样即得到泛型方法。典型的例子如下

class GeneralMethod{
    <Type> void printClassName(Type obj){
        System.out.println(obj.getClass().getName());
    }
}

public class Test {
    public static void main(String[] args){
        GeneralMethod c = new GeneralMethod();
        c.printClassName(3L);
        c.printClassName(3);
        c.printClassName(3.0);
        c.printClassName(3.3f);
        c.printClassName("Hello");
        c.printClassName((Integer)3);
        /*
        java.lang.Long
		java.lang.Integer
		java.lang.Double
		java.lang.Float
		java.lang.String
		java.lang.Integer
        */
    }
}

泛型编程中还可以配合使用?通配符,使得编程更为简洁

class GeneralType <Type>{
    Type obj;
    public GeneralType(Type obj){this.obj = obj;}
    public Type getObj(){
        return obj;
    }
}
class ShowType{
    public void show(GeneralType<?> o){
        System.out.println(o.getObj().getClass().getName());
    }
}
public class Test {
    public static void main(String[] args){
        ShowType st = new ShowType();
        GeneralType<Integer> t = new GeneralType<Integer>(2);
        GeneralType<Double> d = new GeneralType<Double>(4.3d);
        st.show(t); //java.lang.Integer
        st.show(d); //java.lang.Double
	}
}        

泛型不是万能的,我们可以对泛型的类型做一些限制,从而限制那些能够正确处理的类型传进来。实现的方法是在Type后面加上extends关键字,后面接类名或者接口名,限制Type继承自某个类名或者时间某个接口。注意这里接口名前面也是用extends而不是implements。

class GeneralType <Type extends Number>{
    Type obj;
    public GeneralType(Type obj){
        this.obj = obj;
    }
    public Type getObj(){
        return obj;
    }
}
//这里就限制了传进来的Type必须是Number的子类。

你可能感兴趣的:(Java,java)