牛客网刷题day03

1.下列程序执行后结果为( )

class A {
    public int func1(int a, int b) {
        return a - b;
    }
}
class B extends A {
    public int func1(int a, int b) {
        return a + b;
    }
}
public class ChildClass {
    public static void main(String[] args) {
    A a = new B();
    B b = new B();
    System.out.println("Result=" + a.func1(100, 50));
    System.out.println("Result=" + b.func1(100, 50));
    }
}
  • Result=150
    Result=150
  • 涉及转型的题目,分为向上或者向下转型。

    关键的来了,不论向上或者向下转型,都是一句话,“编译看左边,运行看右边”。也就是编译时候,会看左边引用类型是否能正确编译通过,运行的时候是调用右边的对象的方法。 此题考查的是多态。

  •   对于多态,可以总结它为:       

         一、使用父类类型的引用指向子类的对象;

        二、该引用只能调用父类中定义的方法和变量;

        三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)

        四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。

    多态的3个必要条件:

            1.继承   2.重写   3.父类引用指向子类对象。

    向上转型: Person p = new Man() ; //向上转型不需要强制类型转化

    向下转型: Man man = (Man)new Person() ; //必须强制类型转化

2.对于以下代码段,4个输出语句中输出true的个数是(    )。

class A{}
class B extends A{}
class C extends A{}
class D extends B{}
public class Test {
    public static void main(String[] args) {
        A obj = new D();
        System.out.println(obj instanceof B);
        System.out.println(obj instanceof C);
        System.out.println(obj instanceof D);
        System.out.println(obj instanceof A);
    }
}
  • true
    false
    true
    true
  • C直接继承自A,obj的实际类型为D,和C没有关系。所以obj instanceof C 输出false。

3.以下代码将打印出

public static void main(String args[]) {
      List  Listlist1 = new ArrayList();
      Listlist1.add(0);
      List Listlist2 = Listlist1;
        System.out.println(Listlist1.get(0) instanceof Integer);
        System.out.println(Listlist2.get(0) instanceof Integer);
}
  • true true
  • collection类型的集合(ArrayList,LinkedList)只能装入对象类型的数据,该题中装入了0,是一个基本类型,但是JDK5以后提供了自动装箱与自动拆箱,所以int类型自动装箱变为了Integer类型。编译能够正常通过。

    将list1的引用赋值给了list2,那么list1和list2都将指向同一个堆内存空间。instanceof是Java中关键字,用于判断一个对象是否属于某个特定类的实例,并且返回boolean类型的返回值。显然,list1.get(0)和list2.get(0)都属于Integer的实例

4.在类设计中,类的成员变量要求仅仅能够被同一package下的类访问,请问应该使用下列哪个修饰词()

  • 不需要任何修饰词

5.在Java中,以下关于方法重载和方法重写描述正确的是?

  • 方法重写的返回值类型必须相同或相容。
    重载(overload):只要方法名 一致 ,其他(参数列表、返回值)怎么折腾随便。
    重写(overriding):只有实现的功能代码 不一致 ,其他的(函数名、参数列表、返回值类型)必须都一致。
    目前的问题:父类的功能无法满足子类的需求。
    方法重写的前提: 必须要存在继承的关系。
    方法的重写: 子父类出了同名的函数,这个我们就称作为方法的重写。
    什么是时候要使用方法的重写:父类的功能无法满足子类的需求时。
    方法重写要注意的事项:
        1.方法重写时, 方法名与形参列表必须一致。
        2.方法重写时,子类的权限修饰符必须要大于或者等于父类的权限修饰符。
        3.方法重写时,子类的返回值类型必须要小于或者 等于父类的返回值类型。
        4.方法重写时, 子类抛出的异常类型要小于或者等于父类抛出的异常类型。
                Exception(最坏)
                RuntimeException(小坏)
    方法的重载:在一个类中 存在两个或者两个 以上的同名函数,称作为方法重载。
    方法重载的要求
        1. 函数名要一致。
        2. 形参列表不一致(形参的个数或形参 的类型不一致)
        3. 与返回值类型无关。

6.默认类型等价表示是哪一项:

public interface IService {String NAME="default";}
  • public static final String NAME="default";
  • 接口中的变量默认是public static final 的,方法默认是public abstract 的

7.以下代码对其执行后,NumberList里的元素依次为:

public static void main(String args[]) {
        List<Integer> NumberList = new ArrayList<Integer>();
        NumberList.add(2);
        NumberList.add(4);
        NumberList.add(1);
        NumberList.add(3);
        NumberList.add(5);
        for (int i = 0; i < NumberList.size(); ++i) {
            int v = NumberList.get(i);
            if (v % 2 == 0) {
                NumberList.remove(v);
            }
        }
        System.out.println(NumberList);
    }
  • 会出现越界情况
  • 这题主要考察两点:

    1.ArrayList删除元素后,剩余元素会依次向前移动,因此下标一直在变,size()也会减小;

    2.remove()方法调用的是remove(int index),而不是remove(Object o),因此删除的是index索引处的元素;

    该题具体流程:1.i=0,v=2,remove(2)删除掉了元素1,因此NumberList剩余元素为【2,4,3,5】;

                              2.i=1,v=4,remove(4),此时线性表中只有四个元素,不可能删除索引为4的元素,因此会报数组下标越界异常。

8.在一个基于分布式的游戏服务器系统中,不同的服务器之间,哪种通信方式是不可行的()?

  • 管道
  • 对于管道,有下面这几种类型:

    ①普通管道(PIPE):通常有两种限制,一是单工,即只能单向传输;二是血缘,即常用于父子进程间(或有血缘关系的进程间)。

    ②流管道(s_pipe):去除了上述的第一种限制,实现了双向传输。

    ③命名管道(name_pipe):去除了上述的第二种限制,实现了无血缘关系的不同进程间通信。

    显然,要求是对于不同的服务器之间的通信,是要要求全双工形式的,而管道只能是半双工,虽然可以双向,但是同一时间只能有一个方向传输,全双工和半双工的区别可以如下图示理解:

9.What will be printed when you execute the following code?

class C {
    C() {
        System.out.print("C");
    }
}

class A {
    C c = new C();

    A() {
        this("A");
        System.out.print("A");
    }

    A(String s) {
        System.out.print(s);
    }
}

class Test extends A {
    Test() {
        super("B");
        System.out.print("B");
    }

    public static void main(String[] args) {
        new Test();
    }
}
  • CBB
  • 初始化过程是这样的: 

    1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化; 

    2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化; 

    3.其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法;

    4.最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法; 

    (1)初始化父类的普通成员变量和代码块,执行 C c = new C(); 输出C 

    (2)super("B"); 表示调用父类的构造方法,不调用父类的无参构造函数,输出B 

    (3) System.out.print("B"); 

     所以输出CBB

10.Test.main()函数执行后的输出是( )

class Test {
    public static void main(String[] args) {
        System.out.println(new B().getValue());
    }
    static class A {
        protected int value;
        public A (int v) {
            setValue(v);
        }
        public void setValue(int value) {
            this.value= value;
        }
        public int getValue() {
            try {
                value ++;
                return value;
            } finally {
                this.setValue(value);
                System.out.println(value);
            }
        }
    }
    static class B extends A {
        public B () {
            super(5);
            setValue(getValue()- 3);
        }
        public void setValue(int value) {
            super.setValue(2 * value);
        }
    }
}
  • 22 34 17
  • 思考和解决这个题的主要核心在于对java多态的理解。个人理解时,执行对象实例化过程中遵循多态特性 ==> 调用的方法都是将要实例化的子类中的重写方法,只有明确调用了super.xxx关键词或者是子类中没有该方法时,才会去调用父类相同的同名方法。

    Step 1:  new B()构造一个B类的实例

    此时super(5)语句调用显示调用父类A带参的构造函数,该构造函数调用setValue(v),这里有两个注意点一是虽然构造函数是A类的构造函数,但此刻正在初始化的对象是B的一个实例,因此这里调用的实际是B类的setValue方法,于是调用B类中的setValue方法 ==> 而B类中setValue方法显示调用父类的setValue方法,将B实例的value值设置为2 x 5 = 10
    紧接着,B类的构造函数还没执行完成,继续执行setValue(getValue()- 3) // 备注1语句。

    先执行getValue方法,B类中没有重写getValue方法,因此调用父类A的getValue方法。这个方法比较复杂,需要分步说清楚:

  • 调用getValue方法之前,B的成员变量value值为10。
  • value++ 执行后, B的成员变量value值为11,此时开始执行到return语句,将11这个值作为getValue方法的返回值返回出去
  • 但是由于getValue块被try finally块包围,因此finally中的语句无论如何都将被执行,所以步骤2中11这个返回值会先暂存起来,到finally语句块执行完毕后再真正返回出去。
  • 这里有很重要的一点:finally语句块中 this.setValue(value)方法调用的是B类的setValue方法。为什么?因为此刻正在初始化的是B类的一个对象(运行时多态),就像最开始第一步提到的一样(而且这里用了使用了this关键词显式指明了调用当前对象的方法)。因此,此处会再次调用B类的setValue方法,同上,super.关键词显式调用A的setValue方法,将B的value值设置成为了2 * 11 = 22
  • 因此第一个打印项为22。  
  • finally语句执行完毕 会把刚刚暂存起来的11 返回出去,也就是说这么经历了这么一长串的处理,getValue方法最终的返回值是11。
  • 回到前面标注了 //备注1 的代码语句,其最终结果为setValue(11-3)=>setValue(8)
    而大家肯定也知道,这里执行的setValue方法,将会是B的setValue方法。 之后B的value值再次变成了2*8 = 16;

    Step2:  new B().getValue()

    B类中没有独有的getValue方法,此处调用A的getValue方法。同Step 1,

  • 调用getValue方法之前,B的成员变量value值为16
  • value++ 执行后, B的成员变量value值为17,此时执行到return语句,会将17这个值作为getValue方法的返回值返回出去
  • 但是由于getValue块被try finally块包围而finally中的语句无论如何都一定会被执行,所以步骤2中17这个返回值会先暂存起来,到finally语句块执行完毕后再真正返回出去。
  • finally语句块中继续和上面说的一样: this.setValue(value)方法调用的是B类的setValue()方法将B的value值设置成为了2 * 17 = 34
  • 因此第二个打印项为34。
  • finally语句执行完毕 会把刚刚暂存起来的17返回出去。
  • 因此new B().getValue()最终的返回值是17.
  • Step3:  main函数中的System.out.println

    将刚刚返回的值打印出来,也就是第三个打印项:17

    最终结果为 22 34 17。 如果朋友们在看的过程中仍然有疑问,可以亲自把代码复制进去ide,在关键语句打下断点,查看调用方法的对象以及运行时的对象值,可以有更深刻的理解。

11.下列Java代码中的变量a、b、c分别在内存的____存储区存放。

class A {
    private String a = “aa”;
    public boolean methodB() {
        String b = “bb”;
        final String c = “cc”;
    }
}
  • 堆区、栈区、栈区
  • 堆区:只存放类对象,线程共享;

    方法区:又叫静态存储区,存放class文件和静态数据,线程共享;

    栈区:存放方法局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享;

12.static修饰的成员不能访问非static修饰的成员。

abstract修饰一个类,这个类肯定可以被继承,但是final类是不能继承的,所以有矛盾,肯定不能同时用。

java中可以有多个重载的main方法,只有public static void main(String[] args){}是函数入口。

public class TestMain{
    public static void main(String[] args){
        System.out.println("Static main");
        new TestMain().main();
    }
    public void main(){
        System.out.println("main");
    }
}

13.Given:

public class IfTest{
    public static void main(String[]args){
        int x=3;
        int y=1;
        if(x = y)
            System.out.println("Not equal");
        else
            System.out.println("Equal");
    }
}

What is the result?

  • An error at line 5 causes compilation to fall.
  • 这个题考查两个知识点。

    1、Java中,赋值是有返回值的 ,赋什么值,就返回什么值。比如这题,x=y,返回y的值,所以括号里的值是1。

    2、Java跟C的区别,C中赋值后会与0进行比较,如果大于0,就认为是true;而Java不会与0比较,而是直接把赋值后的结果放入括号

14.以下代码执行后输出结果为( )

public class Test
{
    public static Test t1 = new Test();
    {
        System.out.println("blockA");
    }
    static
    {
        System.out.println("blockB");
    }
    public static void main(String[] args)
    {
        Test t2 = new Test();
    }
}
  • blockA
    blockB
    blockA
  • 静态块:用static申明,JVM加载类时执行,仅执行一次 
    构造块:类中直接用{}定义,每一次创建对象时执行 
    执行顺序优先级:静态块>main()>构造块>构造方法 
    静态块按照申明顺序执行,先执行Test t1 = new Test();
    所有先输出blockA,然后执行静态块,输出blockB,最后执行main
    方法中的Test t2 = new Test();输出blockA。
  • 类的加载顺序

    (1) 父类静态对象和静态代码块

    (2) 子类静态对象和静态代码块

    (3) 父类非静态对象和非静态代码块

    (4) 父类构造函数

    (5) 子类 非静态对象和非静态代码块

    (6) 子类构造函数

    其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)

15.Java的跨平台特性是指它的源代码可以在多个平台运行。(错误)

Java的跨平台特性是因为JVM的存在, 它可以执行.class字节码文件,而不是.java源代码。

Java程序初始化的执行顺序:父类静态变量—>父类静态代码块—>子类静态变量—>子类静态代码块—>父类非静态变量—>父类非静态代码块—>父类构造方法—>子类非静态变量—>子类非静态代码块—>子类构造方法。

16.在使用super 和this关键字时,以下描述正确的是

  • 在子类构造方法中使用super()显示调用父类的构造方法,super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
  • super()和this()类似,区别是,super从子类中调用父类的构造方法,this()在同一类内调用其它方法。
  • this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
  • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

17.对于这段代码,以下说法正确的是:

public class Test
{
    public int x;
    public static void main(String []args)
    {
        System. out. println("Value is" + x);
    }
}
  • 非静态变量不能够被静态方法引用
  • 非静态成员只能被类的实例化对象引用,因此这里在静态方法中访问x会造成编译出错

18.如下代码的输出结果是什么?

public class Test {
    public int aMethod(){
        static int i = 0;
        i++;
        return i;
    }
public static void main(String args[]){
    Test test = new Test();
    test.aMethod();
    int j = test.aMethod();
    System.out.println(j);
    }
}
  • 编译失败
  • 静态变量只能在类主体中定义,不能在方法中定义

19.下面哪几个函数 public void example(){....} 的重载函数?()

  • public void example(int m){...}
  • public int example(int m,float f){...}
  • public int example(){..}  (错误)
  • java重载的时候以参数个数和参数类型作为区分,方法名相同,返回类型可以相同也可以不同,但不以返回类型作为区分,所以c也是错的,因为c的参数列表和原来的一样。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值