Java

2019-01-29  本文已影响11人  34sir

Java部分

对String的理解

== equals和HashCode

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = count;
            if (n == anotherString.count) {
                int i = 0;
                while (n-- != 0) {
                    // 比较值 如果值不相同则返回false
                    if (charAt(i) != anotherString.charAt(i))
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

为什么覆盖equals时总要覆盖hashCode?
如果不覆盖 会导致该类无法结合所有基于散列的集合一起正常运作;这样的集合包括HashMap、HashSet和Hashtable

闭包和局部内部类的区别

内部类

仅仅是一个编译时的概念
outer.java里面定义了一个内部类inner 编译成功 会生成两个完全不同的.class文件了 分别是outer.class和outer$inner.class 所以内部类可以和外部类重名

为什么使用内部类?

每个内部类都能独立地继承一个(接口的)实现 所以无论外围类是否已经继承了某个(接口的)实现 对于内部类都没有影响
内部类使得多重继承的解决方案可以弥补接口的一些缺陷

成员内部类

普通的内部类 可以无限制的访问外围类的所有变量和方法

局部内部类和匿名内部类

什么是闭包

把函数以及变量包起来 使得变量的生命周期延长

闭包带来的问题

匿名函数的变量引用 也叫变量引用泄漏 会导致线程安全问题 这也是局部变量需要声明为final的原因

abstract class InnerClass {
public abstract void print();
}
public class Outer {
public  void test1(final String s1) {// 参数必须是final
    //局部内部类
    InnerClass c = new InnerClass() {
        public void print() {
            System.out.println(s1);
        }
    };
    c.print();
}

public  void test2(final String s2) {// 参数必须是final
    //匿名内部类
     new Outer() { //名字可以跟外部类一样
        public void print() {
            System.out.println(s2);
        }
    }.print();
}    
public static void main(String[] args) {
    Outer o=new Outer();
    o.test1("inner1");
    o.test2("inner2");

}
}

静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?

原因:
静态方法和属性属于类 不需要继承机制就可以调用

静态内部类的设计意图

内部类的设计意图

静态内部类的设计意图

成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用

什么是内部类?内部类的作用

String StringBuffer和StringBuilder的区别

        String msg="hello";
        System.out.println(msg.hashCode());
        msg="world";
        System.out.println(msg.hashCode());

结果:
99162322
113318802

hashCode不同 显然已经不是同一个对象

区别

String s2 = “This is only a”;
String s3 = “ simple”;
String s4 = “ test”;
String s1 = s2 + s3 + s4;

这种使用方法 会额外创建一个StringBuffer 之后将StringBuffer转化成Stirng

使用策略

String result = "";
for (String s : hugeArray) {
    result = result + s; //此种方式会不断创建result对象 性能差
}
 
// 使用StringBuilder 推荐用这种方式
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();

对多态的理解

多态由继承实现 可以增加的结构性便于代码的拓展和维护

对反射的理解

大多数框架设计的基础

Class

类本身就是一个对象 java.lang.Class的实例对象
实例化Class对象的三种方式:

通过类的类类型创建该类对象实例:
newInstance

方法的反射

步骤:

成员变量的反射

成员变量也是对象 java.lang.reflect.Field类的对象

Class c = obj.getClass();
Field[] fs = c.getDeclaredFields();  //获取自己申明的所有成员变量

for (Field field : fs) {
//得到成员变量的类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成员变量的名称
String fieldName = field.getName();
System.out.println(typeName+" "+fieldName);
}

构造函数的反射

获取到类类型是反射的第一步

// 第一步先获取Class类型
Class c = obj.getClass();
/*
* 首先构造函数也是对象,是java.lang.Constructor类的对象
* 也就是java.lang. Constructor中封装了构造函数的信息
* 和前面说到的一样,它也有两个方法:
* getConstructors()方法获取所有的public的构造函数
* getDeclaredConstructors()方法得到所有的自己声明的构造函数
*/
//Constructor[] cs = c.getConstructors();
Constructor[] cs = c.getDeclaredConstructors();
for (Constructor constructor : cs) {
//我们知道构造方法是没有返回值类型的,但是我们可以:
System.out.print(constructor.getName()+"(");
//获取构造函数的参数列表 得到的是参数列表的类类型
Class[] paramTypes = constructor.getParameterTypes();
for (Class class1 : paramTypes) {
System.out.print(class1.getName()+",");
}
System.out.println(")");
}

动态加载

编译时刻加载的类是静态加载类;运行时刻加载的类是动态加载类
动态加载类一般基于反射

对注解的理解

概念

插入到代码中的元数据 可以在编译期使用预编译工具进行处理 也可以在运行期进行反射处理
本质上 注解是一种特殊的接口 程序可以通过反射获取

作用

分类

自定义主注解

依赖注入和控制反转

依赖注入实现了控制反转的思想
关于控制反转 简单的比喻: "不要打电话给我们询问面试结果 如果合适 我们会主动打电话给你"
控制反转是指从主动到被动 是所有 框架 最基本的特征 框架制定接口规范(面试要求) 对实现了接口的类进行调用(通过了面试 来上班)

静态代理和动态代理的区别

抽象类和接口的区别

抽象类和接口的应用场景

深拷贝和浅拷贝

创建对象的两种方式:

浅拷贝

按位拷贝 会创建一个新对象有着原始对象属性值的精确拷贝
如果属性是基本数据类型 拷贝的就是基本数据类型的值;如果属性是引用类型 拷贝的就是内存地址(如果其中一个对象改变了这个地址 就会影响到其他对象)

深拷贝

拷贝所有的属性 并且拷贝属性动态分配的内存;当对象和它所引用的对象一起拷贝时就发生深拷贝
相对于浅拷贝 速度慢 开销大

关于泛型

上一篇下一篇

猜你喜欢

热点阅读