牛客 java 选择题每日打卡 Day2
牛客 java 选择题每日打卡 Day2
👩💻博客主页:京与旧铺的博客主页
✨欢迎关注🖱点赞🎀收藏⭐留言✒
🔮本文由京与旧铺原创,csdn 首发!
😘系列专栏:java 学习
👕参考网站:牛客网
💻首发时间:🎞2022 年 5 月 14 日🎠
🎨你做三四月的事,八九月就会有答案,一起加油吧
🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦
🎧最后的话,作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲
图片
🛒导航小助手🎪
[TOC]
🤶选择题 1
start()是开启线程,等待获得时间片,一到获得时间片就执行。所以可能一开启就获得了时间片执行,也有可能等到 two 输出后才获得了时间片。所以 BC 都可能,所以 D 也正确。
🤴选择题 2
Java 线程的各个状态间的关系流程
wait()、sleep()、yield()的理解
1)wait()是 Object 的实例方法,在 synchronized 同步环境使用,作用当前对象,会释放对象锁,需要被唤醒。
2)sleep()是 Thread 的静态方法,不用在同步环境使用,作用当前线程,不释放锁。
3)yield()是 Thread 的静态方法,作用当前线程,释放当前线程持有的 CPU 资源,将 CPU 让给优先级不低于自己的线程用,调用后进入就绪状态。
👧选择题 3
含有 abstract 修饰符的 class 即为抽象类,abstract 类不能创建的实例对象。含有 abstract 方法的类必须定义为 abstract class,abstract class 类中的方法不必是抽象的。abstract class
类中定义抽象方法必须在具体
(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为 abstract 类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为 public abstract 类型,接口中的成员变量类型默认为 public static final。
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
\4. 抽象类中的抽象方法的访问类型可以是 public,protected 和(默认类型,虽然
eclipse 下不报错,但应该也不行),但接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型。
\5. 抽象类中可以包含静态方法,接口中不能包含静态方法
\6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是 public static final 类型,并且默认即为 public static final 类型。
java 只是单继承,但是可以实现多个接口,继承的耦合性太强,java 推荐高内聚低耦合的设计思路,不推荐使用继承。在用继承的情况下,如果还必须要继承另外的接口会很麻烦,尽量用接口,这样在你必须要用到继承的时候就可以用了。抽象类和接口都不能被实例化。接口没有构造方法,不能被实例化,但是抽象方法可以有构造方法,不过不是用来实例化对象的,使用来初始化的。
🥽选择题 4
运行时异常: 都是 RuntimeException 类及其子类异常,如 NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是 Java 编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用 try-catch 语句捕获它,也没有用 throws 子句声明抛出它,也会编译通过。非运行时异常 (编译异常): 是 RuntimeException 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOException、SQLException 等以及用户自定义的 Exception 异常,一般情况下不自定义检查异常。
🧥选择题 5
java 的 4 类流程控制语句
循环语句:while,for,do while
选择语句(分支语句):if,switch
跳转语句:break,continue,break,label
异常处理语句:try catch finally,throw
🥼选择题 6
当 x 和 y 的正负相同时,取余和取模结果相同;
当 x 和 y 的正负不同时,取余结果的符号和 x 相同,取模结果的符号和 y 相同。(口诀:取余取头,取模取尾)
x 为被除数,y 为除数
负数之间取余一定是负数
🎏选择题 7
识别合法的构造方法;
1:构造方法可以被重载,一个构造方法可以通过 this 关键字调用另一个构造方法,this 语句必须位于构造方法的第一行;重载:方法的重载(overload):重载构成的条件:方法的名称相同,但参数类型或参数个数不同,才能构成方法的重载。
2 当一个类中没有定义任何构造方法,Java 将自动提供一个缺省构造方法;3 子类通过 super 关键字调用父类的一个构造方法;4 当子类的某个构造方法没有通过 super 关键字调用父类的构造方法,通过这个构造方法创建子类对象时,会自动先调用父类的缺省构造方法 5 构造方法不能被 static、final、synchronized、abstract、native 修饰,但可以被 public、private、protected 修饰;6 构造方法不是类的成员方法;7 构造方法不能被继承。
🥩选择题 8
补充 Java 内存管理知识:
1. 内存分配策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的。
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间。这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求。
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的。和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存。和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例。堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。
2. JVM 中的堆和栈
JVM 是基于堆栈的虚拟机。JVM 为每个新创建的线程都分配一个堆栈,也就是说,对于一个 Java 程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM 对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
java 把内存分两种:一种是栈内存,另一种是堆内存
栈(stack)与堆(heap)都是 Java 用来在 Ram 中存放数据的地方。与 C++不同,Java 自动管理栈和堆,程序员不能直接地设置栈或堆。
栈(stack):是一个先进后出的数据结构,通常用于保存方法(函数)中的参数,局部变量。
堆(heap):是一个可动态申请的内存空间(其记录空闲内存空间的链表由操作系统维护),是一个运行时数据区,C 中的 malloc 语句所产生的内存空间就在堆中。
3. 堆和栈优缺点比较
栈的优势是,存取速度比堆要快,仅次于直接位于 CPU 中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第 3 点。
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java 的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
4. Java 中的数据类型有两种
一种是基本类型
共有 8 种,即 int, short, long, byte, float, double, boolean, char(注意,并没有 string 的基本类型)。
这种类型的定义是通过诸如 int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如 int a = 3; 这里的 a 是一个指向 int 类型的引用,指向 3 这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。
另外,**栈有一个很重要的特殊性,就是存在栈中的数据可以共享。**假设我们同时定义:
int a = 3;int b = 3;编译器先处理 int a = 3;首先它会在栈中创建一个变量为 a 的引用,然后查找有没有字面值为 3 的地址,没找到,就开辟一个存放 3 这个字面值的地址,然后将 a 指向 3 的地址。接着处理 int b = 3;在创建完 b 的引用变量后,由于在栈中已经有 3 这个字面值,便将 b 直接指向 3 的地址。这样,就出现了 a 与 b 同时均指向 3 的情况。
特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完 a 与 b 的值后,再令 a=4;那么,b 不会等于 4,还是等于 3。在编译器内部,遇到 a=4;时,它就会重新搜索栈中是否有 4 的字面值,如果没有,重新开辟地址存放 4 的值;如果已经有了,则直接将 a 指向这个地址。因此 a 值的改变不会影响到 b 的值。
另一种是包装类数据
如 Integer, String, Double 等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java 用 new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。
String 是一个特殊的包装类数据。即可以用 String str = new String(“abc”);的形式来创建,也可以用 String str = “abc”;的形式来创建(作为对比,在 JDK 5.0 之前,你从未见过 Integer i = 3;的表达式,因为类与字面值是不能通用的,除了 String。而在 JDK 5.0 中,这种表达式是可以的!因为编译器在后台进行 Integer i = new Integer(3)的转换)。前者是规范的类的创建过程,即在 Java 中,一切都是对象,而对象是类的实例,全部通过 new()的形式来创建。Java 中的有些类,如 DateFormat 类,可以通过该类的 getInstance()方法来返回一个新创建的类,似乎违反了此原则。其实不然。该类运用了单例模式来返回类的实例,只不过这个实例是在该类内部通过 new()来创建的,而 getInstance()向外部隐藏了此细节。那为什么在 String str = “abc”;中,并没有通过 new()来创建实例,是不是违反了上述原则?其实没有。
5.String 在内存中的存放
String 是一个特殊的包装类数据,可以用用以下两种方式创建:
String str = new String(“abc”);第一种创建方式是用 new()来新建对象的,它会存放于堆中。每调用一次就会创建一个新的对象。
String str = “abc”; 第二种创建方式先在栈中创建一个对 String 类的对象引用变量 str,然后在栈中查找有没有存放值为”abc”的地址,如果没有,则开辟一个存放字面值为”abc”的地址,接着创建一个新的 String 类的对象 o,并将 o 的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象 o。如果已经有了值为”abc”的地址,则查找对象 o,并返回 o 的地址,最后将 str 指向对象 o 的地址。
值得注意的是,一般 String 类中字符串值都是直接存值的。但像 String str = “abc”;这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!
6.数组在内存中的存放
int x[] 或者 int []x 时,在内存栈空间中创建一个数组引用,通过该数组名来引用数组。
x = new int[5] 将在堆内存中分配 5 个保存 int 型数据的空间,堆内存的首地址放到栈内存中,每个数组元素被初始化为 0。
7.static 变量在内存中的存放
用 static 的修饰的变量和方法,实际上是指定了这些变量和方法在内存中的“固定位置”-static storage。既然要有“固定位置”那么他们的 “大小”似乎就是固定的了,有了固定位置和固定大小的特征了,在栈中或堆中开辟空间那就是非常的方便了。如果静态的变量或方法在不出其作用域的情况下,其引用句柄是不会发生改变的。
8. java 中变量在内存中的分配
1、类变量(static 修饰的变量)
在程序加载时系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期一直持续到整个”系统”关闭
2、实例变量
当你使用 java 关键字 new 的时候,系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”。 实例变量的生命周期–当实例变量的引用丢失后,将被 GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存
3、局部变量
局部变量,由声明在某方法,或某代码段里(比如 for 循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放
Java 中 String 类型变量是 immutable(不可变的)。
尽管 change()方法中的 str 与 sv.str 都是新的对象实例成员变量值"6"的引用, 由于 String 类型的 不可变 性,change()方法中的 str="10"语句实际上是将传入的 str 副本引用指向了一个值为“10”的新的内存地址,但 原数据引用 sv.str 的引用值(也就是“6”的内存地址) 并没有发生改变,因此 sv.str 指向的值仍旧为 6.
🍚选择题 8
🥪选择题 9
其中涉及:静态初始化代码块、构造代码块、构造方法当涉及到继承时,按照如下顺序执行:1、执行父类的静态代码块
static {System.out.println("static A");}输出:static A2、执行子类的静态代码块 static {System.out.println("static B");}输出:static B3、执行父类的构造代码块{System.out.println("I’m A class");}输出:I'm A class4、执行父类的构造函数 public HelloA() {}输出:无 5、执行子类的构造代码块{System.out.println("I’m B class");}输出:I'm B class6、执行子类的构造函数 public HelloB() {}输出:无
那么,最后的输出为:static Astatic BI'm A classI'm B class 正确答案:C
🧀选择题 9
length 得到的是字符,不是字节。
🥗选择题 10
值传递是将变量的一个副本传递到方法中,方法中如何操作该变量副本,都不会改变原变量的值。
引用传递是将变量的内存地址传递给方法,方法操作变量时会找到保存在该地址的变量,对其进行操作。会对原变量造成影响。
🥖选择题 11
1.java 支持单继承,却可以实现多个接口。2.接口没有构造方法,所以不能实例化,抽象类有构造方法,但是不是用来实例化的,是用来初始化的。3.抽象类可以定义普通成员变量而接口不可以,但是抽象类和接口都可以定义静态成员变量,只是接口的静态成员变量要用 static final public 来修饰。
🥙选择题 12
A,start 是开启线程,run 是线程的执行体,run 是线程执行的入口。
**B,**CyclicBarrier 和 CountDownLatch 都可以让一组线程等待其他线程。前者是让一组线程相互等待到某一个状态再执行。后者是一个线程等待其他线程结束再执行。
C,Callable 中的 call 比 Runnable 中的 run 厉害就厉害在有返回值和可以抛出异常。同时这个返回值和线程池一起用的时候可以返回一个异步对象 Future。
D,start 是把线程从 new 变成了 runnable
🍣选择题 13
在 static 方法中是不能访问非静态变量 a 的,需要将 a 声明为 static,答案才会是 0 ,否则是编译出错
🥪选择题 14
在使用匿名内部类的过程中,我们需要注意如下几点:
**1、**使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
**2、**匿名内部类中是不能定义构造函数的。
**3、**匿名内部类中不能存在任何的静态成员变量和静态方法。
**4、**匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
**5、**匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
🥞选择题 15
类加载过程
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7 个阶段。其中准备、验证、解析 3 个部分统称为连接(Linking)。如图所示。
加载、验证、准备、初始化和卸载这 5 个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持 Java 语言的运行时绑定(也称为动态绑定或晚期绑定)。以下陈述的内容都已 HotSpot 为基准。
加载
在加载阶段(可以参考 java.lang.ClassLoader 的 loadClass()方法),虚拟机需要完成以下 3 件事情:
通过一个类的全限定名来获取定义此类的二进制字节流(并没有指明要从一个 Class 文件中获取,可以从其他渠道,譬如:网络、动态生成、数据库等);
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口;
加载阶段和连接阶段(Linking)的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。
验证
验证是连接阶段的第一步,这一阶段的目的是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。验证阶段大致会完成 4 个阶段的检验动作:
文件格式验证:验证字节流是否符合 Class 文件格式的规范;例如:是否以魔术 0xCAFEBABE 开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。
元数据验证:对字节码描述的信息进行语义分析(注意:对比 javac 编译阶段的语义分析),以保证其描述的信息符合 Java 语言规范的要求;例如:这个类是否有父类,除了 java.lang.Object 之外。
字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
符号引用验证:确保解析动作能正确执行。
验证阶段是非常重要的,但不是必须的,它对程序运行期没有影响,如果所引用的类经过反复验证,那么可以考虑采用-Xverifynone 参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。
准备
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被 static 修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量的定义为:
那变量 value 在准备阶段过后的初始值为 0 而不是 123.因为这时候尚未开始执行任何 java 方法,而把 value 赋值为 123 的 putstatic 指令是程序被编译后,存放于类构造器()方法之中,所以把 value 赋值为 123 的动作将在初始化阶段才会执行。至于“特殊情况”是指:public static final int value=123,即当类字段的字段属性是 ConstantValue 时,会在准备阶段初始化为指定的值,所以标注为 final 之后,value 的值在准备阶段初始化为 123 而非 0.
解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类符号引用进行。
初始化
类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的 java 程序代码。在准备极端,变量已经付过一次系统要求的初始值,而在初始化阶段,则根据程序猿通过程序制定的主管计划去初始化类变量和其他资源,或者说:初始化阶段是执行类构造器<clinit>()方法的过程.
<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块 static{}中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问
🧈选择题 16
一般线程调度模式分为两种——抢占式调度和协同式调度。抢占式调度指的是每条线程执行的时间、线程的切换都由系统控制,系统控制指的是在系统某种运行机制下,可能每条线程都分同样的执行时间片,也可能是某些线程执行的时间片较长,甚至某些线程得不到执行的时间片。在这种机制下,一个线程的堵塞不会导致整个进程堵塞。协同式调度指某一线程执行完后主动通知系统切换到另一线程上执行,这种模式就像接力赛一样,一个人跑完自己的路程就把接力棒交接给下一个人,下个人继续往下跑。线程的执行时间由线程本身控制,线程切换可以预知,不存在多线程同步问题,但它有一个致命弱点:如果一个线程编写有问题,运行到一半就一直堵塞,那么可能导致整个系统崩溃。java 采用的是抢占式调度方式。
🍞选择题 17
java 中 String str = "hello world"下列语句错误的是?
ABC 在 java 中会报错,D 可以正常运行, 所以答案是 ABC.
A. 'a'是字符,' a'这个是空格和 a,必须要用" a"才可以;
B.String 有 length()方法
C.int 无法直接转成 String 类型
D.尾部添加字符串”100“
🌭选择题 18
A.文件分为文本文件和二进制文件,计算机只认识二进制,所以实际上都是二进制的不同解释方式。文本文件是以不同编码格式显示的字符,例如 Ascii、Unicode 等,window 中文本文件的后缀名有".txt",".log",各种编程语言的源码文件等;二进制文件就是用文本文档打开是看不懂乱码,只要能用文本打开的文件都可以算是文本文件,只是显示的结果不是你想要的,二进制文件只有用特殊的应用才能读懂的文件,例如".png",".bmp"等,计算机中大部分的文件还是二进制文件。
B.File 类是对文件整体或者文件属性操作的类,例如创建文件、删除文件、查看文件是否存在等功能,不能操作文件内容;文件内容是用 IO 流操作的。
C.当输入过程中意外到达文件或流的末尾时,抛出 EOFException 异常,正常情况下读取到文件末尾时,返回一个特殊值表示文件读取完成,例如 read()返回-1 表示文件读取完成。
D.上面 A 选项已经说了,不论是文本文件还是二进制文件,在计算机中都是以二进制形式存储的,所以都当做二进制文件读取。
🤴总结
好啦,今天的错题总结就到这里啦,以后的每一天我都会尽量去打卡做 java 的基础选择题,然后总结出错题,相信练习之后会有更好的学习效果,既然看到这里啦,可以给我三连一下吗,爱你们啊
评论