码个蛋(codeegg) 第 822 次推文
码妞看世界
1. Java创建对象的几种方式
使用new关键字
使用Class类的newInstance方法
使用Constructor类的newInstance方法
使用clone方法
使用反序列化
2. 重载(overload)和重写(override)的区别
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态 性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为 重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方 法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。
方法重载的规则:
方法名一致,参数列表中参数的顺序,类型,个数不同。
重载与方法的返回值无关,存在于父类和子类,同类中。
可以抛出不同的异常,可以有不同修饰符。
方法重写的规则:
参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写方法的返回类型一致。
构造方法不能被重写,声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,但是能够被再次 声明。
访问权限不能比父类中被重写的方法的访问权限更低。
重写的方法能够抛出任何非强制异常(UncheckedException,也叫非运行时异常),无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则 可以。
3. 谈谈对 java 注解的理解
定义:提供一种为程序元素设置元数据的方法,不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。
功能:
作为特定的标记,用于告诉编译器一些信息
编译时动态处理,如动态生成代码
运行时动态处理,作为额外信息的载体,如得到注解信息
分类:
标准注解:Override、Deprecated、SuppressWarnings 标准 Annotation 是指 Java 自带的几个 Annotation,上面三个分别表示重写函数,不鼓励使用(有更好方式、使用有风险或已不在维护),忽略某项 Warning;
元注解:@Retention、@Target、@Inherited、@Documented 用来定义 Annotation 的 Annotation
自定义注解:自定义 Annotation 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation 这里是一种分类而已,也可以根据作用域分为源码时、编译时、运行时 Annotation
元注解
@Target 用于描述注解的使用范围(即:被描述的注解可以用在什么地方),说明了Annotation所修饰的对象范围,Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
@Retention 定义了该Annotation被保留的时间长短,表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
@Documented 用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
@Inherited 是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
支持的格式:
所有基本数据类型(int,float,boolean,byte,double,char,long,short)
String类型
Class类型
enum类型
Annotation类型
以上所有类型的数组
4. 什么是不可变对象,它对写并发应用有什么帮助
不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects)。
不可变对象的类即为不可变类(Immutable Class)。Java平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。
不可变对象天生是线程安全的。它们的常量(域)是在构造函数中创建的。既然它们的状态无法修改,这些常量永远不会变。
不可变对象永远是线程安全的。
只有满足如下状态,一个对象才是不可变的;
它的状态不能在创建后再被修改;
所有域都是final类型;
并且,它被正确创建(创建期间没有发生this引用的溢出)。
5. 类什么时候被初始化
类初始化阶段是类加载过程的最后阶段。在这个阶段,java虚拟机才真正开始执行类定义中的java程序代码。那么类什么时候会被初始化呢? 1.创建类的实例,也就是new一个对象 2.访问某个类或接口的静态变量,或者对该静态变量赋值 3.调用类的静态方法 4.反射(Class.forName("com.example.load")) 5.初始化一个类的子类(会首先初始化子类的父类) 6.JVM启动时标明的启动类,即文件名和类名相同的那个类
只有这6中情况才会导致类的类的初始化。 类的初始化步骤: 1)如果这个类还没有被加载和链接,那先进行加载和链接 2)假如这个类存在直接父类,并且这个类还没有被初始化(注意:在一个类加载器中,类只能初始化一次),那就初始化直接的父类(不适用于接口) 3) 加入类中存在初始化语句(如static 变量和static块),那就依次执行这些初始化语句。