黑马程序员——java基础面试题之面向对象

来源:互联网 发布:system.out linux 输出 编辑:程序博客网 时间:2024/05/19 03:28

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

成员变量和局部变量的区别?

A:在类中的位置不同成员变量:在类中方法外局部变量:在方法定义中或者方法声明上B:在内存中的位置不同成员变量:在堆内存局部变量:在栈内存C:生命周期不同成员变量:随着对象的创建而存在,随着对象的消失而消失局部变量:随着方法的调用而存在,随着方法的调用完毕而消失D:初始化值不同成员变量:有默认初始化值局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。注意事项:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

静态变量和成员变量的区别

A:所属不同静态变量:属于类,类变量成员变量:属于对象,对象变量,实例变量B:内存位置不同静态变量:方法区的静态区成员变量:堆内存C:生命周期不同静态变量:静态变量是随着类的加载而加载,随着类的消失而消失成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失D:调用不同静态变量:可以通过对象名调用,也可以通过类名调用成员变量:只能通过对象名调用

static关键字注意事项

A:在静态方法中是没有this关键字的如何理解呢?静态是随着类的加载而加载,this是随着对象的创建而存在。静态比对象先存在。B:静态方法只能访问静态的成员变量和静态的成员方法静态方法:成员变量:只能访问静态变量成员方法:只能访问静态成员方法非静态方法:成员变量:可以是静态的,也可以是非静态的成员方法:可是是静态的成员方法,也可以是非静态的成员方法。简单记:静态只能访问静态。
静态代码块,构造代码块,构造方法的执行顺序?

静态代码块 -- 构造代码块 -- 构造方法静态代码块:只执行一次构造代码块:每次调用构造方法都执行
/*写程序的执行结果。林青霞都60了,我很伤心我是main方法Student 静态代码块Student 构造代码块Student 构造方法Student 构造代码块Student 构造方法*/class Student {static {System.out.println("Student 静态代码块");}{System.out.println("Student 构造代码块");}public Student() {System.out.println("Student 构造方法");}}class StudentDemo {static {System.out.println("林青霞都60了,我很伤心");}public static void main(String[] args) {System.out.println("我是main方法");Student s1 = new Student();Student s2 = new Student();}}
Java中继承的特点
A:Java只支持单继承,不支持多继承。有些语言是支持多继承,格式:extends 类1,类2,...B:Java支持多层继承(继承体系)<pre name="code" class="java">/*class Father {}class Mother {}class Son exnteds Father {} //正确的class Son extends Father,Mother {} // 错误的*/

继承的注意事项
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。C:不要为了部分功能而去继承class A {public void show1(){}public void show2(){}}class B {public void show2(){}public void show3(){}}//我们发现B类中出现了和A类一样的show2()方法,所以,我们就用继承来体现class B extends A {public void show3(){}}这样其实不好,因为这样你不但有了show2(),还多了show1()。有可能show1()不是你想要的。
this和super的区别

分别是什么呢?this代表本类对应的引用。super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)怎么用呢?A:调用成员变量this.成员变量 调用本类的成员变量super.成员变量 调用父类的成员变量B:调用构造方法this(...)调用本类的构造方法super(...)调用父类的构造方法C:调用成员方法this.成员方法 调用本类的成员方法super.成员方法 调用父类的成员方法
继承中构造方法的关系

A:子类中所有的构造方法默认都会访问父类中空参数的构造方法B:为什么呢?因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。注意:子类每一个构造方法的第一条语句默认都是:super();
如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?

/*报错。如何解决呢?A:在父类中加一个无参构造方法B:通过使用super关键字去显示的调用父类的带参构造方法C:子类通过this去调用本类的其他构造方法子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。注意事项:this(...)或者super(...)必须出现在第一条语句上。如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。*/class Father {/*public Father() {System.out.println("Father的无参构造方法");}*/public Father(String name) {System.out.println("Father的带参构造方法");}}class Son extends Father {public Son() {super("随便给");System.out.println("Son的无参构造方法");//super("随便给");}public Son(String name) {//super("随便给");this();System.out.println("Son的带参构造方法");}}class ExtendsDemo7 {public static void main(String[] args) {Son s = new Son();System.out.println("----------------");Son ss = new Son("林青霞");}}
方法重写的注意事项

A:父类中私有方法不能被重写因为父类私有方法子类根本就无法继承B:子类重写父类方法时,访问权限不能更低最好就一致C:父类静态方法,子类也必须通过静态方法进行重写其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解子类重写父类方法的时候,最好声明一模一样。
看程序写结果

/*看程序写结果:A:成员变量就近原则B:this和super的问题this访问本类的成员super访问父类的成员C:子类构造方法执行前默认先执行父类的无参构造方法D:一个类的初始化过程成员变量进行初始化默认初始化显示初始化构造方法初始化结果:fuzi302010*/class Fu{public int num = 10;public Fu(){System.out.println("fu");}}class Zi extends Fu{public int num = 20;public Zi(){System.out.println("zi");}public void show(){int num = 30;System.out.println(num); //30System.out.println(this.num); //20System.out.println(super.num); //10}}class ExtendsTest {public static void main(String[] args) {Zi z = new Zi();z.show();}}
/*看程序写结果:A:一个类的静态代码块,构造代码块,构造方法的执行流程静态代码块 > 构造代码块 > 构造方法B:静态的内容是随着类的加载而加载静态代码块的内容会优先执行C:子类初始化之前先会进行父类的初始化结果是:静态代码块Fu静态代码块Zi构造代码块Fu构造方法Fu构造代码块Zi构造方法Zi*/class Fu {static {System.out.println("静态代码块Fu");}{System.out.println("构造代码块Fu");}public Fu() {System.out.println("构造方法Fu");}}class Zi extends Fu {static {System.out.println("静态代码块Zi");}{System.out.println("构造代码块Zi");}public Zi() {System.out.println("构造方法Zi");}}class ExtendsTest2 {public static void main(String[] args) {Zi z = new Zi();}}

/*看程序写结果:A:成员变量的问题int x = 10; //成员变量是基本类型Student s = new Student(); //成员变量是引用类型B:一个类的初始化过程成员变量的初始化默认初始化显示初始化构造方法初始化C:子父类的初始化(分层初始化)先进行父类初始化,然后进行子类初始化。结果:YXYZ问题:虽然子类中构造方法默认有一个super()初始化的时候,不是按照那个顺序进行的。而是按照分层初始化进行的。它仅仅表示要先初始化父类数据,再初始化子类数据。*/class X {Y b = new Y();X() {System.out.print("X");}}class Y {Y() {System.out.print("Y");}}public class Z extends X {Y y = new Y();Z() {//super();System.out.print("Z");}public static void main(String[] args) {new Z(); }}
方法重写和方法重载的区别?方法重载能改变返回值类型吗?

方法重写:在子类中,出现和父类中一模一样的方法声明的现象。方法重载:同一个类中,出现的方法名相同,参数列表不同的现象。方法重载能改变返回值类型,因为它和返回值类型无关。Override:方法重写Overload:方法重载
this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this:代表当前类的对象引用super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)场景:成员变量:this.成员变量super.成员变量构造方法:this(...)super(...)成员方法:this.成员方法super.成员方法
final关键字

/*final可以修饰类,方法,变量特点:final可以修饰类,该类不能被继承。final可以修饰方法,该方法不能被重写。(覆盖,复写)final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。常量:A:字面值常量"hello",10,trueB:自定义常量final int x = 10;*///final class Fu //无法从最终Fu进行继承class Fu {public int num = 10;public final int num2 = 20;/*public final void show() {}*/}class Zi extends Fu {// Zi中的show()无法覆盖Fu中的show()public void show() {num = 100;System.out.println(num);//无法为最终变量num2分配值//num2 = 200;System.out.println(num2);}}class FinalDemo {public static void main(String[] args) {Zi z = new Zi();z.show();}}
/*面试题:final修饰局部变量的问题基本类型:基本类型的值不能发生改变。引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。*/class Student {int age = 10;}class FinalTest {public static void main(String[] args) {//局部变量是基本数据类型int x = 10;x = 100;System.out.println(x);final int y = 10;//无法为最终变量y分配值//y = 100;System.out.println(y);System.out.println("--------------");//局部变量是引用数据类型Student s = new Student();System.out.println(s.age);s.age = 100;System.out.println(s.age);System.out.println("--------------");final Student ss = new Student();System.out.println(ss.age);ss.age = 100;System.out.println(ss.age);//重新分配内存空间//无法为最终变量ss分配值ss = new Student();}}
/*final修饰变量的初始化时机A:被final修饰的变量只能赋值一次。B:在构造方法完毕前。(非静态的常量)*/class Demo {//int num = 10;//final int num2 = 20;int num;final int num2;{//num2 = 10;}public Demo() {num = 100;//无法为最终变量num2分配值num2 = 200;}}class FinalTest2 {public static void main(String[] args) {Demo d = new Demo();System.out.println(d.num);System.out.println(d.num2);}}
/*继承的代码体现由于继承中方法有一个现象:方法重写。所以,父类的功能,就会被子类给覆盖调。有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。这个时候,针对这种情况,Java就提供了一个关键字:finalfinal:最终的意思。常见的是它可以修饰类,方法,变量。*/class Fu {public final void show() {System.out.println("这里是绝密资源,任何人都不能修改");}}class Zi extends Fu {// Zi中的show()无法覆盖Fu中的show()public void show() {System.out.println("这是一堆垃圾");}}class ZiDemo {public static void main(String[] args) {Zi z = new Zi();z.show();}}
多态的前提

A:要有继承关系。B:要有方法重写。其实没有也是可以的,但是如果没有这个就没有意义。动物 d = new 猫();d.show();动物 d = new 狗();d.show();C:要有父类引用指向子类对象。父 f =  new 子();
多态中的成员访问特点

A:成员变量编译看左边,运行看左边。B:构造方法创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。C:成员方法编译看左边,运行看右边。D:静态方法编译看左边,运行看左边。(静态和类相关,算不上重写,所以,访问还是左边的)由于成员方法存在方法重写,所以它运行看右边。
class Fu {public int num = 100;public void show() {System.out.println("show Fu");}public static void function() {System.out.println("function Fu");}}class Zi extends Fu {public int num = 1000;public int num2 = 200;public void show() {System.out.println("show Zi");}public void method() {System.out.println("method zi");}public static void function() {System.out.println("function Zi");}}class DuoTaiDemo {public static void main(String[] args) {//要有父类引用指向子类对象。//父 f =  new 子();Fu f = new Zi();System.out.println(f.num);//找不到符号//System.out.println(f.num2);f.show();//找不到符号//f.method();f.function();}}
多态的好处

A:提高了代码的维护性(继承保证)B:提高了代码的扩展性(由多态保证)<pre name="code" class="java">多态的弊端:不能使用子类的特有功能。

如何实现父类使用子类的特有功能?

A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)B:把父类的引用强制转换为子类的引用。(向下转型)对象间的转型问题:向上转型:Fu f = new Zi();向下转型:Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
ClassCastException:类型转换异常,一般在多态的向下转型中容易出现

class Animal {public void eat(){}}class Dog extends Animal {public void eat() {}public void lookDoor() {}}class Cat extends Animal {public void eat() {}public void playGame() {}}class DuoTaiDemo5 {public static void main(String[] args) {//内存中的是狗Animal a = new Dog();Dog d = (Dog)a;//内存中是猫a = new Cat();Cat c = (Cat)a;//内存中是猫Dog dd = (Dog)a; //ClassCastException}}
看程序写结果

/*看程序写结果:先判断有没有问题,如果没有,写出结果*/class Fu {public void show() {System.out.println("fu show");}}class Zi extends Fu {public void show() {System.out.println("zi show");}public void method() {System.out.println("zi method");}}class DuoTaiTest3 {public static void main(String[] args) {Fu f = new Zi();//找不到符号//f.method();f.show();}}
/*看程序写结果:先判断有没有问题,如果没有,写出结果多态的成员访问特点:方法:编译看左边,运行看右边。继承的时候:子类中有和父类中一样的方法,叫重写。子类中没有父亲中出现过的方法,方法就被继承过来了。*/class A {public void show() {show2();}public void show2() {System.out.println("我");}}class B extends A {/*public void show() {show2();}*/public void show2() {System.out.println("爱");}}class C extends B {public void show() {super.show();}public void show2() {System.out.println("你");}}public class DuoTaiTest4 {public static void main(String[] args) {A a = new B();a.show();B b = new C();b.show();}}
抽象类的特点

A:抽象类和抽象方法必须用abstract关键字修饰B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类C:抽象类不能实例化因为它不是具体的。抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?用于子类访问父类数据的初始化D:抽象的子类a:如果不想重写抽象方法,该子类是一个抽象类。b:重写所有的抽象方法,这个时候子类是一个具体的类。抽象类的实例化其实是靠具体的子类实现的。是多态的方式。Animal a = new Cat();
抽象类的成员特点

成员变量:既可以是变量,也可以是常量。构造方法:有。用于子类访问父类数据的初始化。成员方法:既可以是抽象的,也可以是非抽象的。抽象类的成员方法特性:A:抽象方法 强制要求子类做的事情。B:非抽象方法 子类继承的事情,提高代码复用性。
abstract不能和哪些关键字共存

private冲突final冲突static无意义
接口的特点

A:接口用关键字interface表示interface 接口名 {}B:类实现接口用implements表示class 类名 implements 接口名 {}C:接口不能实例化那么,接口如何实例化呢?按照多态的方式来实例化。D:接口的子类a:可以是抽象类。但是意义不大。b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
接口成员特点

成员变量;只能是常量,并且是静态的。默认修饰符:public static final建议:自己手动给出。构造方法:接口没有构造方法。成员方法:只能是抽象方法。默认修饰符:public abstract建议:自己手动给出。
interface Inter {public int num = 10;public final int num2 = 20;public static final int num3 = 30;//错误: 需要<标识符>//public Inter() {}//接口方法不能带有主体//public void show() {}//abstract void show(); //默认publicpublic void show(); //默认abstract}//接口名+Impl这种格式是接口的实现类格式/*class InterImpl implements Inter {public InterImpl() {super();}}*/class InterImpl extends Object implements Inter {public InterImpl() {super();}public void show() {}}//测试类class InterfaceDemo2 {public static void main(String[] args) {//创建对象Inter i = new InterImpl();System.out.println(i.num);System.out.println(i.num2);//i.num = 100;//i.num2 = 200;//System.out.println(i.num); //无法为最终变量num分配值//System.out.println(i.num2);//无法为最终变量num2分配值System.out.println(Inter.num);System.out.println(Inter.num2);System.out.println("--------------");}
修饰符

修饰符:权限修饰符:private,默认的,protected,public状态修饰符:static,final抽象修饰符:abstract类:权限修饰符:默认修饰符,public状态修饰符:final抽象修饰符:abstract用的最多的就是:public成员变量:权限修饰符:private,默认的,protected,public状态修饰符:static,final用的最多的就是:private构造方法:权限修饰符:private,默认的,protected,public用的最多的就是:public成员方法:权限修饰符:private,默认的,protected,public状态修饰符:static,final抽象修饰符:abstract用的最多的就是:public除此以外的组合规则:成员变量:public static final成员方法:public static           public abstract  public final
成员内部类

/*成员内部类:如何直接访问内部类的成员。外部类名.内部类名 对象名 = 外部类对象.内部类对象;*/class Outer {private int num = 10;class Inner {public void show() {System.out.println(num);}}}class InnerClassDemo3 {public static void main(String[] args) {//需求:我要访问Inner类的show()方法//Inner i = new Inner();//i.show();//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;Outer.Inner oi = new Outer().new Inner();oi.show();}}
局部内部类

/*局部内部类A:可以直接访问外部类的成员B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能面试题:局部内部类访问局部变量的注意事项?A:局部内部类访问局部变量必须用final修饰B:为什么呢?局部变量是随着方法的调用而调用,随着调用完毕而消失。而堆内存的内容并不会立即消失。所以,我们加final修饰。加入final修饰后,这个变量就成了常量。既然是常量。你消失了。我在内存中存储的是数据20,所以,我还是有数据在使用。*/class Outer {private int num  = 10;public void method() {//int num2 = 20;//final int num2 = 20;class Inner {public void show() {System.out.println(num);//从内部类中访问本地变量num2; 需要被声明为最终类型System.out.println(num2);//20}}//System.out.println(num2);Inner i = new Inner();i.show();}}class InnerClassDemo5 {public static void main(String[] args) {Outer o = new Outer();o.method();}}
匿名内部类

/*匿名内部类就是内部类的简化写法。前提:存在一个类或者接口这里的类可以是具体类也可以是抽象类。格式:new 类名或者接口名(){重写方法;}本质是什么呢?是一个继承了该类或者实现了该接口的子类匿名对象。*/interface Inter {public abstract void show();public abstract void show2();}class Outer {public void method() {//一个方法的时候/*new Inter() {public void show() {System.out.println("show");}}.show();*///二个方法的时候/*new Inter() {public void show() {System.out.println("show");}public void show2() {System.out.println("show2");}}.show();new Inter() {public void show() {System.out.println("show");}public void show2() {System.out.println("show2");}}.show2();*///如果我是很多个方法,就很麻烦了//那么,我们有没有改进的方案呢?Inter i = new Inter() { //多态public void show() {System.out.println("show");}public void show2() {System.out.println("show2");}};i.show();i.show2();}}class InnerClassDemo6 {public static void main(String[] args) {Outer o = new Outer();o.method();}}

按照要求,补齐代码

/*匿名内部类面试题:按照要求,补齐代码interface Inter { void show(); }class Outer { //补齐代码 }class OuterDemo {public static void main(String[] args) {  Outer.method().show();  }}要求在控制台输出”HelloWorld”*/interface Inter { void show(); //public abstract}class Outer { //补齐代码public static Inter method() {//子类对象 -- 子类匿名对象return new Inter() {public void show() {System.out.println("HelloWorld");}};}}class OuterDemo {public static void main(String[] args) {Outer.method().show();/*1:Outer.method()可以看出method()应该是Outer中的一个静态方法。2:Outer.method().show()可以看出method()方法的返回值是一个对象。又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。*/}}
面试题
/*面试题:要求请填空分别输出30,20,10。注意:1:内部类和外部类没有继承关系。2:通过外部类名限定this对象Outer.this*/class Outer {public int num = 10;class Inner {public int num = 20;public void show() {int num = 30;System.out.println(num);System.out.println(this.num);//System.out.println(new Outer().num);System.out.println(Outer.this.num);}}}class InnerClassTest {public static void main(String[] args) {Outer.Inner oi = new Outer().new Inner();oi.show();}}
晕。。。。。终于收集完了


0 0
原创粉丝点击