1、类和对象有什么区别?
Java的类通过class关键字定义,它代表了一个抽象的集合,类里面可以定义属性和方法,它们代表了每个类实例的数据和动作。Java虚拟机只对类加载一次,对静态变量也只加载一次。
对象是指某一个特性抽象的实例,属于某一种类型,也就是对象是通过类创建的。它必须从属于某一个类,通过new关键字来创建,代表了一个特定类型的实例,可以被多次创建。
总之,类是一种抽象,对象是类的实现。
2、Java中如何使用继承来重用代码?
Java中的继承只有单继承,也就子类只能继承一个父类,而不能继承多个父类。继承使用extends关键字。继承过后,子类就拥有父类除开私有成员以外的所有成员,从而达到代码重用的目的。继承过程中,可以通过方法的覆盖来实现多态,让子类拥有自己独特的方法实现方式。
3、简述Java中的多态
子类对父类的方法进行覆盖,让子类拥有自己独特的方法实现方式。
“多态”->多种形式,多种状态。本质是,发送消息的某个对象,让该对象自行决定响应何种行为。通过子类对象引用赋值给超类对象引用变量来实现动态方法的调用。
多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。
4、介绍Java中静态成员的特点
使用static关键字修饰的成员,有三种:静态成员变量、静态方法、静态代码块。
public class Test{
static int a;//静态变量
statuc void test(){//静态方法
System.out.println("test.....");
}
static{//静态代码块
System.out.println("execute static code....");
}
public static void main(String[] args){
System.out.println(a);
Test t = new Test();
t.test();
}
}
执行结果:
execute static code....
0
test.....
执行以上代码时,jvm会先加载Test类到内存中来,然后创建a变量进行初始化,在执行static代码块。在main()方法中,创建了一个Test类的实例对象t,通过t来访问静态方法test()。
静态成员特点:
- 在类加载的时候,就进行创建和初始化;
- 一个类中,只有一份;
- 类的所有实例都可以访问。
5、简述Java派生类中的构造方法如何为父类传递参数
super关键字是用来访问父类的成员的,他可以调用被子类重写的父类成员方法,也可以调用父类的构造方法。
class Father{
public static void prt(String s) {
System.out.println(s);
}
Father(){
prt("父类·无参数构造方法: "+"A Father.");
}
Father(String name){
prt("父类·含一个参数的构造方法: "+"A Father's name is " + name);
}
}
class Child extends Father{
Child(){
super();
prt("子类·调用父类”无参数构造方法“: "+"A Child.");
}
Child(String name){
super(name);
prt("子类·调用父类”含一个参数的构造方法“: "+"his name is " + name);
}
Child(String name, int age) {
this(name);// 调用具有相同形参的构造方法(3)
prt("子类:调用子类具有相同形参的构造方法:his age is " + age);
}
}
public class TestExtends {
public static void main(String[] args) {
Child ch = new Child();
ch = new Child("aaaa");
ch = new Child("aaaa", 18);
}
}
运行结果:
父类·无参数构造方法: A Father.
子类·调用父类”无参数构造方法“: A Child.
父类·含一个参数的构造方法: A Father's name is aaaa
子类·调用父类”含一个参数的构造方法“: his name is aaaa
父类·含一个参数的构造方法: A Father's name is aaaa
子类·调用父类”含一个参数的构造方法“: his name is aaaa
子类:调用子类具有相同形参的构造方法:his age is 18
本例中,Child类第三种构造方法调用的是本类中第二种构造方法,而第二种构造方法是调用父类的,因此也要先调用父类的构造方法,再调用本类中第二种,最后是重写第三种构造方法。
在Java中,使用super加括号()的形式来为父类的构造方法传递参数,通过参数的数目和类型判断调用哪一个构造方法。如果调用的是父类的无参构造方法,可以不写super()。
6、简述接口和抽象类的区别
抽象类通过abstract class定义,不可以实例化;
接口通过该interface定义,不能被直接实例化,实现类通过implements关键字来声明实现的接口。
一个实现类只能继承一个抽象类,但是可以实现多个接口。
7、简述内部类的实质
内部类分为四种:
- 静态内部类:使用static关键字修饰的内部类,例如:
class Outter{//外部类
static class inner{//定义静态内部类
....
}
}
在外部类加载的时候,静态内部类也随之加载,它的完整的类名字是Outter.Inner,编译后的class文件名为“Outter$Inner.class”。因为静态内部类是静态的,所以无法访问外部类的非静态成员。
静态内部类相对于外部类来说,仅仅是包含关系,缩小命名空间,完整类名中多了一个外部类的名称,本质上是两个独立的类,JVM也不知道这两个类的包含关系。
- 成员内部类:没有使用static修饰的内部类
class OutterB{//外部类
class Inner{//内部类
....
}
}
此时的内部类需要等外部类创建了对象以后才能被加载到JVM中,它属于外部类的某个实例,因此成员内部类可以外部类的静态和非静态成员。
创建成员内部类的时候,首先创建一个外部类的实例,然后应这个实例调用new语句。
public static void main(String[] args){
Outter o = new Outter();//外部类实例
Outter.Inner i = o.new Inner();//创建内部类实例
}
对于成员内部类的构造方法来说,系统会自动加上一个外部类的参数以及一个外部类的成员变量,为了遵循先有外部类实例才能有内部类实例的原则。
class Inner(Outter o){//成员内部类的本质构造方法
this.o = o;
}
当内部类访问外部类成员时,则是通过自动添加的成员变量进行访问。
- 局部内部类:仅在定义它的方法中有效。
public void test(){//成员方法
class aaa{//定义局部内部类
...
}
}
局部内部类也是独立的类,但是不能使用static关键字,智能使用final、abstract关键字,仅可以访问外部类带有的final关键字的局部变量,也可以访问外部类对象的成员变量。
当局部内部类定义在静态方法中时就相当于静态内部类;当定义在普通的成员方法中,则相当于成员内部类。
- 匿名内部类:如果一个类没有名字,则它是匿名内部类。
public void test(){//成员方法
new aaaa(){
public void bbbMethod(){
....
}
}
}
匿名内部类的定义和使用根本没有出现class关键字,但事实上还是创建了。以上代码中,该类实现了aaaa接口,直接在方法体中就提供具体的实现,如果需要提供构造方法的参数,则直接在aaaa后边的那个括号中提供即可,工作原理相当于局部内部类,外部不能直接使用它。
匿名内部类编译后的class文件的命名是按照匿名内部类的排列顺序来进行,直接在外部类后面加上“$”/和序号,例如,Outter$1.class。