类和对象

一.注意点:

1.凭经验可知,如果需要返回一个可变数据域的拷贝,就应该使用克隆。
2.子类的构造器不能访问父类的私有域,所以必须利用父类的构造器对这部分私有数据进行初始化,可以使用super关键字调用父类构造器进行初始化,并且super语句必须是子类构造器的第一条语句。
3.如果子类构造器没有显式调用父类构造器进行初始化,那么系统将会自动调用父类构造器的默认构造器,即无参构造器。如果超类没有无参构造器,并且子类构造器没有显式调用父类构造器,Java编译器将会报错。
4.方法的名字和参数列表合称为方法的签名。返回类型不是签名的一部分,因此在覆盖方法时,一定要保证返回类型的兼容性。允许子类将覆盖方法的返回类型定义为原返回类型的子类型。
5.在覆盖一个方法时,子类方法的可见性不能低于父类方法的可见性。
6.final类中的所有方法都是final的,不能被覆盖,但是final类中的域不一定是final的。
7.在早期的Java中,程序员避免动态绑定的系统开销而使用final关键字。如果一个方法没有被覆盖而且很短,编译器能对其进行优化处理,这个过程称为内联。如果虚拟机加载了另外一个子类,并且该子类中包含了对内联方法的覆盖,优化器将会取消对覆盖方法的内联。
8.进行类型转换的唯一原因:暂时忽视对象的类型后,使用对象的全部功能。
9.再将超类转换为子类时,应该使用instanceof进行检查。Java中,需要将instanceof运算符和类型转换结合起来使用。
如果x为null,x instanceof C不会产生异常,只是返回false。
10.类即使不含有抽象方法,也可以将类声明为抽象类。可以定义一个抽象类的对象变量,但是他们只能引用非抽象子类的对象。
11.字符串s和t拥有相同的hashcode,这是因为字符串的hashcode是根据内容计算的,而缓存字符串sb和st有着不同的哈希值,这是因为stringbuilder类中没有hashCode()方法,他们的散列码是由Object类默认的hashcode方法导出的对象存储地址。如果重新定义了equals方法,就必须重新定义hashCode()方法。

public static void main(String[] args) {
        String s = "hello";
        StringBuilder sb = new StringBuilder(s);
        System.out.println(s.hashCode() + " " + sb.hashCode());

        String t = "hello";
        StringBuilder st = new StringBuilder(t);
        System.out.println(t.hashCode() + " " + st.hashCode());
    }

equals()和hashCode()的定义必须一致。
12.在程序运行期间,Java运行时系统始终为为每一个对象维护一个被称为运行时类型标识。虚拟机利用运行时类型信息选择相应的方法执行。

二.Java反射机制
1.获得class类对象的三种方法:
1.通过该类的对象获得
Employee e = new Employee();
String typeName = e.getClass().getName();//类名包括包名
2.通过forName()获得

已知类名,可以通过该方法获得类对象

String className = "java.util.Random";
Class c1 = Class.forNamw(className);

以上方法只有在className为类名或者接口名时才能够执行,否则forName方法会抛出一个checked exception。因此无论何时使用这个方法,都应该提供一个类型处理器。

3.通过类名.class获得
Class c1 = Random.class;
Class c2 = int.class;
Class c3 = Double[].class;

class对象实际上表示的是一个类型,而这个类型实际上并非是一种类。
int不是类,但是int.class是Class类型的对象。
#####2.将forName和newInstance方法结合可以根据存储在字符串中的类名创建对象

String s = "java.util.Random";
Object m = Class.forName(s).newInsrance();

以上创建对象的方式中,要求s表示的类名的必须有一个默认的构造器(没有参数的构造器),否则会抛出异常。

1.打印类中的实例域
    /**
     * print all fields of a class
     * @param cl
     */
    public static void printFields(Class cl) {

        Field[] fields = cl.getDeclaredFields();
        for(Field field : fields){
            Class type = field.getType();
            String fieldName = field.getName();
            System.out.print("  ");
            String modifiers = Modifier.toString(field.getModifiers());

            if(modifiers.length() > 0)
                System.out.print(modifiers + " ");
            System.out.println(type.getName() + " " + fieldName + ";");
        }
    }
2.打印类中的构造函数
    /**
     * print all constructors of a class
     * @param cl
     */
    public static void printConstructors(Class cl) {
        Constructor[] constructors = cl.getDeclaredConstructors();
        for (Constructor constructor : constructors){
            String constructorName = constructor.getName();
            System.out.print("  ");
            String modifier = Modifier.toString(constructor.getModifiers());
            if(modifier.length() > 0)
                System.out.print(modifier + " ");
            System.out.print(constructorName + "(");

            //print parameter types
            Class[] parameterTypes = constructor.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                if(i > 0)
                    System.out.print(",");
                System.out.print(parameterTypes[i].getName());
            }
            System.out.println(");");
        }
    }
3.打印类中的方法
    /**
     * print all methods of a class
     * @param cl
     */
    public static void printMethods(Class cl){

        Method[] methods = cl.getDeclaredMethods();
        for (Method method : methods){
            System.out.print("  ");
            String modifiers = Modifier.toString(method.getModifiers());
            if(modifiers.length() > 0)
                System.out.print(modifiers + " ");
            //获取返回类型
            Class returnType = method.getReturnType();
            System.out.print(returnType.getName() + " " + method.getName() + "(");
            //打印方法参数类型
            Class[] parameterTypes = method.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                if(i > 0)
                    System.out.print(",");
                System.out.print(parameterTypes[i].getName());
            }
            System.out.println(");");
        }
    }
三.继承的设计技巧

1.将公共操作和域放在超类中;
2.不要使用受保护的域(protected);
3.使用继承实现"is-a"关系;
4.除非所有的继承方法都有意义,否则不要使用继承;
5.在覆盖方法时,不要改变预期的行为;
6.使用多态,而非根据类型检查执行响应的代码;
7.不要过多的使用反射,反射比较脆弱,编译器很难帮助人们发现程序中的错误,因此只有在运行时才发现错误并导致异常。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值