大厂笔试选择题总结(持续更新)

前言

实时更新

主要总结的部分是java后台的开发岗位
主要是通过刷各个公司以及市场上中的选择题笔记
以下都是博主经常错或者可能需要掌握的一些技术点
(主要是选择题某个难以理解的知识点或者是整个知识点都拷贝下来)

正文

以下选择题没有顺序重要性

1. 接口

接口中方法的默认修饰符时public abstract,抽象方法可是没有方法体的,没有大括号{}
JDK8中,接口中的方法可以被default和static修饰,但是!!!被修饰的方法必须有方法体
接口是可以多继承的,但抽象方法不能有方法体

2. 值传递和引用传递

主要通过代码进行考察

  • 值传递主要是 字符串,String类是final类型的,不能继承和修改这个类
  • 引用传递主要是通过对象、数组
    在这里插入图片描述

3. 非静态变量

非静态变量不能够被静态方法引用

非静态成员只能被类的实例化对象引用,因此这里在静态方法中访问x会造成编译出错

public class Test
{
    public int x;
    public static void main(String []args)
    {
        System. out. println("Value is" + x);
    }
}

4. JVM参数

  • Xmx10240m:代表最大堆
  • -Xms10240m:代表最小堆
  • -Xmn5120m:代表新生代
  • -XXSurvivorRatio=3:代表Eden:Survivor = 3 根据Generation-Collection算法(目前大部分JVM采用的算法),一般根据对象的生存周期将堆内存分为若干不同的区域,一般情况将新生代分为Eden ,两块Survivor; 计算Survivor大小, Eden:Survivor = 3,总大小为5120,3x+x+x=5120 x=1024

新生代大部分要回收,采用Copying算法,快!
老年代 大部分不需要回收,采用Mark-Compact算法

5. 字节流和字符流

区分它的判定可以通过
stream结尾都是字节流,reader和writer结尾都是字符流

字节流:
InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream

字符流
Reader
|-- InputStreamReader (byte->char 桥梁)
|-- BufferedReader (常用)
Writer
|-- OutputStreamWriter (char->byte 桥梁)
|-- BufferedWriter
|-- PrintWriter (常用)

6. final

  1. final修饰变量,则等同于常量
    final修饰变量,变量的引用(也就是指向的地址)不可变,但是引用的内容可以变(地址中的内容可变)。
  2. final修饰方法中的参数,称为最终参数。
  3. final修饰类,则类不能被继承
  4. final修饰方法,则方法不能被重写。

5. final 不能修饰抽象类

6. final修饰的方法可以被重载 但不能被重写

注意重载和重写的区别
重写(Overriding)是父类与子类之间多态性的一种表现,类的不同实现可以重写父类方法,实现同方法名,同参数,同返回类型,不同的实现。
重载(Overloading)最典型的就是一个类的不同构造函数,方法名相同,参数个数不同,返回类型也可以不同,重载是一个类中多态性的一种表现。

补充一下finalize
在这里插入图片描述

7. 多态

某个代码编译测试题

class Base
{
    public void method()
    {
        System.out.println("Base");
    } 
}
class Son extends Base
{
    public void method()
    {
        System.out.println("Son");
    }
    
    public void methodB()
    {
        System.out.println("SonB");
    }
}
public class Test01
{
    public static void main(String[] args)
    {
        Base base = new Son();
        base.method();
        base.methodB();
    }
}

测试结果为编译不通过
new 了一个派生类,赋值给基类,所以下面的操作编译器认为base对象就是Base类型的
Base类中不存在methodB()方法,所以编译不通过
要想调用的话需要先通过SON son=(SON)base;强制转换,然后用son.methodB()调用就可以了。

8. jvm

在这里插入图片描述

一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法, 并且在下一次垃圾回收动作发生时,才会真正的回收对象占用的内存(《java 编程思想》)
在C++中,对象的内存在哪个时刻被回收,是可以确定的,在C++中,析构函数和资源的释放息息相关,能不能正确处理析构函数,关乎能否正确回收对象内存资源。
在java中,对象的内存在哪个时刻回收,取决于垃圾回收器何时运行,在java中,所有的对象,包括对象中包含的其他对象,它们所占的内存的回收都依靠垃圾回收器,因此不需要一个函数如C++析构函数那样来做必要的垃圾回收工作。当然存在本地方法时需要finalize()方法来清理本地对象。在《java编程思想》中提及,finalize()方法的一个作用是用来回收“本地方法”中的本地对象


java的堆内存分为两块:permantspace(持久带) 和 heap space

  • heapspace分为年轻带和年老带
  • 持久带中主要存放用于存放静态类型数据,如 Java Class, Method 等, 与垃圾收集器要收集的Java对象关系不大。

关于jvm的堆内存

  • 年老代溢出原因有 循环上万次的字符串处理、创建上千万个对象、在一段代码内申请上百M甚至上G的内存。设置的内存参数Xmx过小或程序的内存泄露及使用不当问题。这种情况下除了检查程序、打印堆内存等方法排查,还可以借助一些内存分析工具,比如MAT就很不错。
  • 持久代溢出原因 -动态加载了大量Java类而导致溢出。解决办法唯有将参数 -XX:MaxPermSize 调大(一般256m能满足绝大多数应用程序需求)。将部分Java类放到容器共享区(例如Tomcat share lib)去加载的办法也是一个思路,但前提是容器里部署了多个应用,且这些应用有大量的共享类库

关于异常机制
如果try语句里有return,返回的是try语句块中变量值。
详细执行过程如下:

  • 如果有返回值,就把返回值保存到局部变量中;
  • 执行jsr指令跳到finally语句里执行;
  • 执行完finally语句后,返回之前保存在局部变量表里的值。

如果try,finally语句里均有return,忽略try的return,而使用finally的return.

9. servlet

  • ServletContext对象:servlet容器在启动时会加载web应用,并为每个web应用创建唯一的servlet context对象,可以把ServletContext看成是一个Web应用的服务器端组件的共享内存,在ServletContext中可以存放共享数据。ServletContext对象是真正的一个全局对象,凡是web容器中的Servlet都可以访问。整个web应用只有唯一的一个ServletContext对象
  • servletConfig对象:用于封装servlet的配置信息。从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对servlet自身有效,一个servlet的ServletConfig对象不能被另一个servlet访问。通过ServletConfig接口的getInitParameter()方法可以获得Servlet的初始化参数

10. 单例模式

具体更多的详情可看我这篇文章
JAVA设计模式之单例模式详细分析(全)

详情可看这道例题

class Chinese{
private static Chinese objref =new Chinese();
private Chinese(){}
public static Chinese getInstance() { return objref; }
}

public class TestChinese {
public static void main(String [] args) {
Chinese obj1 = Chinese.getInstance();
Chinese obj2 = Chinese.getInstance();
System.out.println(obj1 == obj2);
}
}

单例模式,obj1和obj2其实是一个对象,应该返回true!

11. 泛型

这道题感觉就是一个新世界,补充了很多知识点
题目如下

class A {}
class B extends A {}
class C extends A {}
class D extends B {}

下面的判断对与错

public static void main(String[] args) {
	List<A> a;
	List list;
	list = a;   //对,因为List就是List<?>,代表最大的范围,A只是其中的一个点

	List<B> b;
	a = b;      //错,点与点之间不可相互赋值

	List<?> qm;
	List<Object> o;
	qm = o;     //对,List<?>代表最大的范围,List<Object>只是一个点
	
	List<D> d;
	List<? extends B> downB;
	downB = d;  //对,List<? extends B>代表小于等于B的范围,List<D>是一个点

	List<?extends A> downA;
	a = downA;  //错,范围不能赋值给点
	a = o;      //错,List<Object>只是一个点,不可点赋值给点
	downA = downB;  //对,小于等于A的范围包含小于等于B的范围,B是A的子类

}
  • 尖括号里的是一个类,那么尖括号里的就是一个点,比如List,List,List
  • 尖括号里面带有问号,那么代表一个范围,<? extends A> 代表小于等于A的范围,<? super A>代表大于等于A的范围,<?>代表全部范围
  • List<?>和List 是相等的,都代表最大范围

点不可相互赋值,除非是相同的点,小范围可以赋值给大范围,大范围不可赋值给小范围

12. ==

相对于字符串来说

String str1="hello";
//str1指的是方法区中的字符串常量池中的“hello”,编译时期就知道的

String str2="he"+ new String("llo");
//str2必须在运行时才知道str2是什么,所以它是指向的是堆里定义的字符串“hello”,所以这两个引用是不一样的

String str3="hello";
String str4=new String("Hello");
String str5="hel"+"lo";
        
System.out.println(str1==str2); //false
System.out.println(str1==str3); //true
System.out.println(str1==str4); //false
System.out.println(str1==str5); //true

String str1=“hello”; 这样创建字符串是存在于常量池中
String str2=new String(“hello”); str2存在于堆中


相对于包装类来说

Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);

==比较的是地址
但是当为基本类型时,比较的是值
如果俩边有包装类型,则先将包装类型转换为基本类型在比较值是否相等。
当俩边都为包装类型时,即为对象,比较的是地址

13. Math函数

Math.floor() 表示向下取整,返回double类型 (floor—地板)
Math.ceil() 表示向上取整,返回double类型 (ceil—天花板)
Math.round() 四舍五入,返回int类型

14. import

Java提供了包机制。包是类的容器,用于分隔类名空间。如果没有指定包名,所有的示例都属于一个默认的无名包。Java中的包一般均包含相关的类,java是跨平台的,所以java中的包和操作系统没有任何关系,java的包是用来组织文件的一种虚拟文件系统。

import语句并没有将对应的java源文件拷贝到此处仅仅是引入,告诉编译器有使用外部文件,编译的时候要去读取这个外部文件。

定义在同一个包(package)内的类可以不经过import而直接相互使用。

15. 数组

数组的写法可以这样写都对(注意第二种)

  • float f[][] = new float[6][6];
  • float []f[] = new float[6][6];
  • float [][]f = new float[6][6];
  • float [][]f = new float[6][];

代码问答题

class X{
	Y y=new Y();
	public X(){
		System.out.print("X");
	}
}
class Y{
	public Y(){
		System.out.print("Y");
	}
}
public class Z extends X{
	Y y=new Y();
	public Z(){
		System.out.print("Z");
	}
	public static void main(String[] args) {
		new Z();
	}
}

在这里插入图片描述

(1)初始化父类的普通成员变量和代码块,执行 Y y=new Y(); 输出Y
(2)再执行父类的构造方法;输出X
(3) 初始化子类的普通成员变量和代码块,执行 Y y=new Y(); 输出Y
(4)再执行子类的构造方法;输出Z
所以输出YXYZ


interface Com{
    int M=200;
    int f();
}
class ImpCom implements Com{
    【代码】
}

将下列(A、B、C、D)哪个代码替换下列程序中的【代码】不会导致编译错误?
public int f(){return 100+M;}
int f(){return 100;}
public double f(){return 2.6;}
public abstract int f();

答案是第1个
1、必须实现接口中所有的方法。
在实现类中实现接口时,方法的名字、返回值类型、参数的个数及类型必须与接口中的完全一致,并且必须实现接口中的所有方法。
2、接口实现类相当于子类,子类的访问权限是不能比父类小的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值