1、如何实现对象克隆
1)实现Cloneable接口并重写Object类中的clone();
2)实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现深度克隆;
2、深拷贝和浅拷贝区别?
1)浅复制(浅克隆):仅复制所考虑的对象,不复制它所引用的对象。
2)深复制(深克隆):把对象及其引用的对象都复制一遍。
3、深拷贝和浅拷贝如何实现激活机制?
想要执行深层拷贝(deep copy),只需要在TestClone1 t1=(TestClone1)t.clone();后面加上t1.next=(TestClone1)t.next.clone();
4、写clone()方法时,通常都有一行代码,是什么?
super.clone();负责产生正确大小的空间,并逐位复制。
5、在比较对象时,==和equals运算有何区别?
==比较对象的内存地址和内容是否相同,是则为true,否则false。
equals()比较对象的内容是否相同,相同则为true,否则false。
6、如果要重写一个对象的equals方法,还要考虑什么?
重写父类的equals方法时,也重写hashcode方法,使相等的两个对象获取的HashCode也相等,当对象做Map中Key时,两个equals为true的对象获取的value相同;
7、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
错,equals相等则hashcode一定相等;
8、构造器链是什么?
构造一个类实例时, 将会调用沿着继承链的所有父类的构造方法。 当构造一个子类对象时, 子类构造方法在完成自己的任务之前, 首先调用它的父类构造方法。 如果父类继承自其他类, 那么父类构造方法又会在完成自己的任务之前,调用它自己的父类构造方法。 这个过程持续到沿着这个继承体系结构的最后一个构造方法被调用为止。
9、创建对象时构造器的调用顺序?
1)首先调用基础类的构建器,即它的父类构建器,这个步骤会一直持续下去
2)按照声明的顺序调用成员初始化模块
3)调用当前对象类本身的构建器
10、什么是不可变象(immutable object)?
指对象一旦被创建,状态不能再改变。任何修改都会创建一个新对象,如String、Integer及其它包装类。
11、为什么Java中的String是不可变的(Immutable)?
1)字符串中常量池的需要
java中字符串对象都保存在字符串常量池中,创建字符串时首先从这个常量池中查找是否已经存在相同的字符串对象,不存在才会创建新的字符串对象。如果字符串设计成可变的,当修改一个字符串时可能影响其他指向常量池的相同对象。
2)HashCode缓存
保证哈希值唯一性,避免哈希冲突。不必在每次使用集合中的String对象时重复计算哈希值,高效率。
3)线程安全
能够在不同线程中共享,同时确保线程安全,帮助开发者减少线程同步工作。
12、如何构建不可变的类结构?关键点在哪里?
一个类的实例化对象被创建并初始化,那么它就不可改变。可以调用访问器方法(getter),复制对象或传递对象,但不允许任何方法改变这个对象的状态。
包装类(Integer或Float等)和String类是不可变类的代表。
访问器方法(access method):对成员变量做出访问的方法,如getter()方法
修改器方法(mutator method):对成员变量做出修改的方法,如setter()方法
如果要创建一个不可变类,需要遵守下面的规则:
1)将成员变量(field)声明成final并在构造器中初始化;
对于基本类型的成员变量,用final修饰。对于引用类型的成员变量,不能改变它的引用。引用类型是可变的,要采取一些措施来保证它的不可变性。
a)方法不会改变可变对象中的内容
b)不要将引用分享到外部供其他类使用
c)如果必须要返回一个引用,就返回一个对象的深度拷贝
2)只提供访问器方法(如getter方法)不提供修改器方法(如setter方法)
3)如果一定要改变对象内容,那就创建一个新的不可变对象内容作相应修改,返回修改后对象的引用;
4)声明类是final的。如果一个类可以被继承,那么它的子类可以重载它的方法,并且修改成员变量;设计不可变类最关键的一点:注意引用类型的成员变量,如果成员变量的类型是可变的引用类型,就必须要采取必要的措施来保护这个成员变量不会被修改;
13、能创建一个包含可变对象的不可变对象吗?
不可以重复实例化对象引用名称相同的对象,可以重复实例化类型相同而引用名称不同的对象。
14、构造器(constructor)是否可被重写(override)?
构造器不能被继承,不能被override(重写),可以被overloading(重载)。
15、方法可以同时是static又是synchronized吗?
可以,这么做锁的对象是Class级别的;
16、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
都不可以,abstract声明的方法要求子类去实现,具体实现,抽象方法不关心。static方法是不会被覆盖的,而abstract方法正是要子类去覆盖它。总的来说,就是java语法不允许这样做,也没有意义。
17、Java支持哪种参数传递类型?
1)值传递:方法调用时,把参数值传递给相应的形参,方法执行中形参值的改变不影响实际参数值。
2)引用传递:方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形参,在方法执行中,对形参的操作就是对实际参数的操作,方法执行中形参值的改变会影响实际参数的值。
18、一个对象被当作参数传递到一个方法,是值传递还是引用传递?
Java中的方法只接受值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象内容可以在被调用的方法中改变,但对象的引用永远不会改变。
19、能否重载main()方法?
可以重载main()方法,但只有public static void main(String [] args)在JVM启动时被使用。JVM总是查找方法签名来启动程序。
正常的main方法充当JVM启动程序执行的入口点。可以重载main方法,程序运行时,不会执行重载的main方法。
20、如果main方法被声明为private会怎样?
编译可以通过,但运行时会找不到主方法,因为权限不足。
21、解释下多态性(polymorphism),封装性(encapsulation),内聚(cohesion)以及耦合(coupling)?
Java的三大特性:多态、封装、继承。
Java程序设计思想:高内聚、低耦合。
继承:是指可以使用现有类的所有功能,并在无需重新编写原来类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。继承的实现方式有三类:实现继承、接口继承和可视继承。
实现继承:是指使用基类的属性和方法而无需额外编码的能力;
接口继承:是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
可视继承:是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。
封装:是把客观事物封装成抽象类,并且类可以把自己的数据和方法只让可信的类或对象操作,对不可信的进行信息隐藏。
多态:是指一个类实例的相同方法在不同情形有不同表现形式。实现多态方式:覆盖,重载。
高内聚、低耦合:模块与模块间应该尽可能的避免发生联系,假如某一模块因为某种原因需要改动,但是这一模块的改动需要改动整个项目,这样就会延长开发周期,甚至出现不必要的bug。同样,一个模块间的功能尽可能多发生联系,能减少冗余,从而提高项目的可维护性和执行效率。
22、多态的实现原理
Java里对象方法的调用是依靠类信息里的方法表实现的,虽然对象方法引用调用和接口方法引用调用的实现有所不同但大致思想是一样的。总体而言,当调用对象某个方法时,JVM查找该对象类的方法表以确定该方法的直接引用地址,有了地址后才真正调用该方法。
23、对象封装的原则是什么?
简化用户接口,隐藏实现细节,是封装的根本目的,难点在于如何设计接口。
1)必须保证接口是功能的全集,即接口能够覆盖所有需求。
2)尽量使接口是最小冗余的。冗余接口是允许的,但必须保证冗余接口是有效的。 也就是说,增加冗余接口会带来很大的好处,比如性能提升。
3)要保证接口是稳定的,将接口和实现分离,并将实现隐藏,就是为了能保护类使用者在类的实现细节改变的情况下,不必随时修改。一旦接口被公布,永远也不要改变它。
24、获得一个类的类对象有哪些方式?
1)通过类本身来获得对象
Class classname = this .getClass();
2)通过子类实例获取父类对象
ClassName cn = new ClassName();
UserClass = cn.getClass();
Class SubUserClass = UserClass.getSuperclass();
3)通过类名加.class获取对象
Class ForClass = **.**.ClassName.class ;(类在包中的路径加. class )
4)通过类名的字符串获取对象
Class ForName = Class.forName( "**.**.ClassName" );
25、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
方法的重载和重写都是实现多态的方式。
1)重载是编译时的多态性,重写是运行时的多态性。
2)重载发生在一个类中,同名的方法如果有不同的参数列表则为重载,对返回类型没有特殊要求;
重写发生在子类与父类间,要求子类被重写方法与父类被重写方法有相同的返回类型,不能比父类被重写方法声明更多的异常(里氏代换原则)。
重载的方法不可以根据返回类型进行区分。重载使类可以有具有多个相同方法名的方法,编译器可以通过方法的参数类型和个数来区分他们,而返回值和异常是不能作为区别标志的。
26、抽象类和接口的区别?
语法层面上的区别
1)抽象类可以提供成员方法的实现细节,接口中只能存在public abstract方法;
2)抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型;
3)抽象类可以有静态代码块和静态方法,接口中不能含有静态代码块以及静态方法;
4)一个类只能继承一个抽象类,却可以实现多个接口。
设计层面上的区别
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整体进行抽象,包括属性、行为,但接口却是对类局部(行为)进行抽象。
2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。
27、抽象类中是否可以有静态的main方法?
可以
28、抽象类是否可实现(implements)接口?
可以
29、抽象类是否可继承实体类(concrete class)?
可以继承实体类,前提是实体类必须有明确的构造函数。
1)没写构造器的,拥有默认无参公有构造函数的,子类可以什么都不写,让默认构造器去调用它。
2)写了子类可访问的无参构造器的,子类里可以什么都不写,用默认机制调用。
3)写了有参构造器却没写无参构造器的,父类里没有子类可访问的无参构造器,子类必须在子类构造器里的第一句写明,调用父类有参构造器,并把参数传进去。
4)声明为final的以及所有构造器都不在子类访问权限之内的类无法继承;
30、匿名类(Anonymous Inner Class)匿名内部类是否可以继承其它类?是否可以实现接口?
可以继承其他类或实现其他接口
31、内部类分为几种?
1)静态内部类:作为类的静态成员,存在于某个类的内部。
静态内部类虽然是外部类的成员,但在未创建外部类对象的情况下,可以直接创建静态内部类的对象。静态内部类可以引用外部类的静态成员变量和静态方法,但不能引用外部类的普通成员。
2)成员内部类:作为类的成员,存在于某个类的内部。
成员内部类可以调用外部类的所有成员,但只有在创建了外部类的对象后,才能调用外部的成员。
3)局部内部类:存在于某个方法的内部。
局部内部类只能在方法内部中使用,一旦方法执行完毕,局部内部类就会从内存中删除。
注意:如果局部内部类中要使用他所在方法中的局部变量,就需要将这个局部变量定义为final的。
4)匿名内部类:存在于某个类的内部,是无类名的类。
匿名内部类的定义与对象的创建合并在一起,匿名内部类一般通过如下形式定义,并且在定义的同时进行对象的实例化;
new 类或者接口的名字(){
//匿名内部类的主体,这个主体就是类或接口的实现,如果是类, 那么匿名内部类是该类的子类,如 果是接口,匿名内部类需要完成接口的实现。
}
32、内部类可以引用它的包含类(外部类)的成员吗?
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
33、请说一下Java中为什么要引入内部类、匿名内部类?
内部类定义在类的内部,可以方便访问外部类的变量和方法,并且和其它类进行隔离。每个内部类都能各自继承某一实现类,因此内部类不受限于外部类是否已继承自某一实现类。如果少了内部类所提供的“继承自多个具象(concrete)或抽象(abstract)类”的能力,设计和编程上的某些问题会变得十分棘手。所以从某个角度来看inner class,你可以说它是多重继承问题的完整解决方案。interface能够解决其中一部分问题,但内部类才能有效而实际地允许“多重实现继承(multiple implementation)”。也就是说inner classes实际上允许你继承多个non-interface。
inner classes:
1)inner class可以拥有多份实体(instances),每个实体都拥有专属的状态信息(state information),而这些信息和outer class对象的信息是相互独立的。
2)在单一outer class内你可以拥有多个innner classes,每个都实现相同的interface,或以不同方式继承同一个class。
3)产生inner class对象的时间点,不见得必须和产生outer class对象同时。
4)outer class和inner class之间不存在is-a的关系,inner class是独立个体。
匿名内部类可以访问外部类所有的变量和方法。匿名内部类使用广泛,比如常用的绑定监听的时候。
34、继承(Inheritance)与聚合(Aggregation)的区别在哪里?
继承Inheritance:指一个类(子类)继承另一个类(基类),并增加自己的功能,可以通过重写基类中的函数来实现。可以将继承理解成“IS A”的关系。
关联Association:是类之间很弱的一种联系,表现为一个类作为另一个类方法的参数。
聚合Aggregation:是整体和部分的关系,通过从别的类中拿来函数来组成一个新类,或在新类中添加其他代码的一个常用接口Interface。可以将聚合理解成“HAS A”。
组合Composition:和聚合类似,也是表示整体和部分的关系,但不同的是,整体和部分具有统一的生存期,一旦整体不存在了,部分也就没有了。可以将组合理解成“CONTAIN A"。
35、为什么类只能单继承,接口可以多继承?
多继承容易带来安全隐患,当多个父类中实现了相同方法但内容功能不同时,子类对象不确定要运行哪一个。 接口中的方法都是方法名,没有函数体,具体的实现需要靠实现类去实现,一旦实现类实现了方法,那么就不存在多个接口有相同方法名的问题了,因为函数体都是一样的。
36、存在两个类,B继承A,C继承B,能将B转换为C么?如C=(C)B
可以向下转型。这属于强制类型转换,如果被转换的B实例不是C类型,会有异常。
37、如果类a继承类b,实现接口c,而类b和接口c中定义了同名变量,请问会出现什么问题?
在编译时会发生错误。对于父类的变量可以用super.x来明确,而接口的属性默认隐含为public static final,可以通过c.x来明确。
38、接口是什么?
是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
39、接口是否可继承接口?
接口可以继承接口,但要使用extends,抽象类可以实现接口,抽象类可以继承实体类。
40、为什么要使用接口而不是直接使用具体类?接口有什么优点?
1)利于代码的规范
2)有利于对代码进行维护
3)保证代码的安全和严密
41、泛型的存在是用来解决什么问题?
泛型用一个通用的数据类型T来代替object,在类实例化时指定T的类型,运行时(Runtime)自动编译为本地代码,运行效率和代码质量都有很大提高,并且保证数据类型安全。
42、泛型的常用特点?
类型擦除:在生成的Java字节代码中是不包含泛型中的类型信息的。使用泛型时加上的类型参数,会被编译器在编译时去掉,这个过程称为类型擦除。
泛型类并没有自己独有的Class类对象。静态变量是被泛型类的所有实例共享的。
泛型的类型参数不能用在Java异常处理的catch语句中。因为异常处理是由JVM在运行时进行的,由于类型信息被擦除,JVM无法区分两个异常类型MyException
泛型的检测:不符合泛型T的检测,在进行编译之前就对所有泛型进行检测,加入类型检测和转换的指令,比如返回泛型的结果,实际返回的是擦除后的类型,而虚拟机会多加一个类型转换指令。
43、需要泛型之间的类型转换怎么做?通配符?
用PECS(Producer Extends Consumer Super),如果你想遍历collection,并对每一项元素操作时,此时这个集合是生产者(生产元素),应该使用 Collection extends E>,相对于泛型E,能放进E中的(把Collection中的元素放入E类型中) ,应该是E的子类型。
频繁往外读取内容的,适合用上界extends。经常往里插入的,适合用下界super。
44、List能否转为List类型?
用了泛型无法直接赋值,也无法进行类型的强行转换;
方法:先消除泛型,再赋值,编译通过但运行时可能会出现类型转换异常;
45、什么是 Java 的反射机制?
就是在程序运行的时候根据类名及路径动态装载类,生成对象或操作生成对象。
46、Interface 与 abstract 类的区别?
语法区别:
1)抽象类可以有构造方法,接口中不能有构造方法。
2)抽象类中可以有普通成员变量,接口中没有普通成员变量。
3)抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4.)抽象类中的抽象方法的访问类型可以是public,protected和default,但接口中的抽象方法只能是public类型的,并且默认为public abstract类型。
5.)抽象类中可以包含静态方法,接口中不能包含静态方法。
6.)抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认为public static final类型。
7.)一个类可以实现多个接口,但只能继承一个抽象类。
应用上的区别:
接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用。
47、Override和Overload的区别?
override(重写,覆盖)
1)方法名、参数、返回值相同。
2)子类方法不能缩小父类方法的访问权限。
3)子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
4)存在于父类和子类之间。
5)方法被定义为final不能被重写。
overload(重载,过载)
1)参数类型、个数、顺序至少有一个不相同。
2)不能重载只有返回值不同的方法名。
3)存在于父类和子类、同类中。
48、一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?
可以,但只能有一个public类,并且public的类名必须与文件名相一致。