- 抽象类和接口的区别?
抽象类:抽象出来的父类模板,对一种事物的抽象,总结出一些通用的方法,留出来不同的以便子类实现
a.抽象类必须有abstract修饰,此类不能实例化
b.有abstract修饰的方法,类必须声明为abstract,而且不能有方法体的实现,但是抽象类里可以没有抽象方法。
c.子类必须重写父类中的抽象方法,抽象类只能被继承,如果子类没有实现父类中的抽象方法,子类必须也声明为抽象类
d.可以有构造器,抽象方法可以有public,protect,default修饰,不能是private的,子类没办法实现
接口:方法集合,对行为的抽象,他一般用来声明一些规范、行为出来,具体行为子类自行实现
a.成员变量默认是public
static final的; 方法默认是public
abstract(抽象类中的可以是各种类型)
b.子类必须重写接口中所有的方法,接口方法不能有具体实现(抽象类可以提供带有实现的方法)
c.接口中不能有静态代码块以及静态方法,(而抽象类可以有)
d.一个类可以实现多个接口,但是只能继承一个抽象类
2.java 创建一个对象的方法有哪些?
a.使用new创建,最常见,最简单的,会调用构造函数
b.使用Class的newInstance(),会调用构造函数
c.通过Constructor调用类的构造器,然后再通过newInstance()去创建类,
d.使用clone()方法,需要实现Cloneable,重写clone方法,jvm会自动为我们创建一个新的对象,并将所有内容都复制到新的对象,不会调用构造函数
e.通过反序列化去获取一个对象,需要实现Serializable
jvm会创建一个独立的对象,不会调用构造函数
public class Method4NewClass implements Cloneable, Serializable {
public String name;
public Method4NewClass(){
System.out.println("Call Method4NewClass construcetor...");
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
@Override
protected Object clone(){
Object obj= null;
try {
obj = super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return obj;
}
public static void main(String[] args) throws Exception{
Method4NewClass method1 = new Method4NewClass();
method1.setName("method1");
System.out.println("Method1: "+ method1.getName());
Method4NewClass method2 = Method4NewClass.class.newInstance();
method2.setName("method2");
System.out.println("Method2: "+ method2.getName());
Constructor<Method4NewClass> constructor = Method4NewClass.class.getConstructor();
Method4NewClass method3 = constructor.newInstance();
method3.setName("method3");
System.out.println("Method3: "+ method3.getName());
//必须实现Coloneable接口
Method4NewClass method4 = (Method4NewClass) method3.clone();
System.out.println("Method4 -1: "+ method4.getName());
method4.setName("method4");
System.out.println("Method4 -2: "+ method4.getName());
//序列化,存储类到文件,类需要实现Serializable
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
out.writeObject(method4);
out.close();
//反序列化,读取
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Method4NewClass method5 = (Method4NewClass) in.readObject();
System.out.println("Method5 -1: "+ method5.getName());
method5.setName("method5");
System.out.println("Method5 -1: "+ method5.getName());
}
}
运行结果:
可以看到方法1,2,3,是会调用构造函数的,但是clone和序列化就不会去调用构造函数,但是复制或者反序列化读取出来的数据,都是复制源或者序列化的数据。
Call Method4NewClass construcetor...
Method1: method1
Call Method4NewClass construcetor...
Method2: method2
Call Method4NewClass construcetor...
Method3: method3
Method4 -1: method3
Method4 -2: method4
Method5 -1: method4
Method5 -1: method5
说明:如果使用eclipse 是需要显示声明,private static final long serialVersionUID = 1L; 或者其他数值,类似于一个版本标记的作用。
测试代码用IDEA运行的,没有定义也没有报错,运行也正常。
如果缺省,是根据类名,方法,变量等,自动生成一个数值。
网友评论