互联网校招笔试题分享

Java 一些知识点

Object 有哪些方法

  • public 方法:getClassequals(和==之间的区别)hashCodetoStringwaitnotify
  • protected 方法:clonefinalize
  • private 方法:registerNatives,该方法作用是将不同平台C/C++实现的方法映射到Java中的native方法
public class Object {
    private static native void registerNatives();
    // 声明后有紧接静态代码块
    static {
        registerNatives();
    }
}

  

自动装箱

public static void main(String[] args) {
    int i = 0;
    Integer j = new Integer(0);
    System.out.println(j == i);
    System.out.println(j.equals(i));
}

  上述代码的输出是

true
true

 

Java 虚拟机 GC 根节点的选择

  Java通过可达性分析来判断对象是否存活。基本思想是通过一系列称为”GC roots”的对象作为起始点,可以作为根节点的是:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象

作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表)中。
虚拟机栈、本地方法栈这都是局部变量,某个方法执行完,某些局部使用的对象可以被回收。

类加载机制

  • 启动类加载器( Bootstrap ClassLoader)启动类加载器无法被 java 程序员直接引用, 这个类加载器负责把存放在<JAVA_HOME>\lib目录中的, 或者被-Xbootclasspath参数指定路径中的, 并且是被虚拟机识别的类库加载到虚拟机内存中.
  • 扩展类加载器(Extension ClassLoader)负责加载在<JAVA_HOME>\lib\ext目录中的, 或者被java.ext.dirs系统变量所指定的路径中的所有类库。
  • 应用程序类加载器( Application ClassLoader )这个类加载器是ClassLoader 中的 getSystemClassLoader()方法的返回值, 一般称其为系统类加载器, 它负责加载用户类路径( ClassPath )上所指定的类库

从 java 虚拟机的角度而降, 只存在两种不同的类加载器: 

  • 一个是启动类加载器( Bootstrap ClassLoader ), 这个类加载使用 C++ 语言实现, 是虚拟机自身的一部分;
  • 另一种是其他所有的类加载器, 他们由 java 语言实现, 独立于虚拟机之外, 并且全部继承自java.lang.ClassLoader

加载类的寻找范围就是 JVM 默认路径加上Classpath, 类具体是使用哪个类加载器不确定。

类加载主要步骤

  • 加载 把 class 文件的二进制字节流加载到 jvm 里面
  • 验证 确保 class 文件的字节流包含的信息符合当前 jvm 的要求 有文件格式验证, 元数据验证, 字节码验证, 符号引用验证等
  • 准备 正式为类变量分配内存并设置类变量初始值的阶段, 初始化为各数据类型的零值
  • 解析 把常量值内的符号引用替换为直接引用的过程
  • 初始化 执行类构造器<clinit>()方法
  • 使用 根据相应的业务逻辑代码使用该类
  • 卸载 类从方法区移除

双亲委派模型

  除了顶层的启动类加载器之外, 其余的类加载器都应当有自己的父类加载器, 父子关系这儿一般都是以组合来实现。

工作过程: 如果一个类加载器收到了类加载的请求, 它首先不会自己去尝试加载这个类, 而是把这个请求委派给父类加载器去完成, 最终所有的加载请求都会传送到顶层的启动类加载器中, 只有当父类加载器反馈自己无法完成这个请求时候, 才由子加载器来加载。

例如类Object,它放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。

对于任何一个类, 都需要由加载它的类加载器和这个类本身一同确定其在 java 虚拟机中的唯一性。

ClassLoader.loadClass()的代码如下,先检查是否已经被加载过,如果没有则parent.loadClass()调用父加载器的loadClass()方法,如果父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载器加载失败,抛出ClassNotFoundException,再调用自己的findClass()方法进行加载。

另外,如果我们自己实现类加载器,一般是Override复写 findClass方法,而不是loadClass方法。

protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        Class c = findLoadedClass(name);
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                if (parent != null) {
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                c = findClass(name); //可以Override该方法
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

  

Java 后台的一点知识

JSP 与 Servlet 的关系

  • Tomcat 等 Web 容器最终会把 JSP转化为 Servlet
  • Jsp更擅长表现于页面显示, Servlet更擅长于逻辑控制
  • Servlet是利用 System.out.println()来输出 html 代码,由于包括大量的HTML标签、大量的静态文本及格式等,导致Servlet的开发效率低下
  • JSP通过在标准的HTML页面中嵌入Java代码,其静态的部分无须Java程序控制,Java 代码只控制那些动态生成的信息
  • 最终 JSP 被容器解释为 Servlet,其中Html 代码也是用System.out.println()等拼接输出的
  • JSP 第一次访问的时候,要转化为 java 文件,然后编译为 class 文件,所以第一次访问 JSP 速度会比较慢,后面会快很多

Servlet 生命周期

  主要是java.servlet.Servlet接口中的init() 、service() 、和destroy() 3个方法。

  • 初始化阶段,web容器通过调用init()方法来初始化Servlet实例,在Servlet的整个生命周期类,init()方法只被调用一次
  • 客户请求到来时,容器会开始一个新线程,并调用servlet的 service()方法,service() 方法根据请求的http方法来调用 doget() 或dopost()
  • 终止阶段调用destroy()方法,销毁一些资源

GET 请求 vs POST 请求

  • GET用于信息获取,是安全的和幂等的,GET一般是对后台数据库的信息进行查询
  • POST表示可能修改变服务器上的资源的请求,一般是对后台数据库进行增、删、改的操作
  • GET请求的参数会跟在URL后进行传递,请求的数据会附在URL之后,以?分割URL和传输数据,参数之间以&相连,一般浏览器对 URL 的长度会有限制
  • POST请求,提交的数据则放置在是HTTP包的包体中,用类似Key-Value的格式发送一些数据,相对来说,GET请求会把请求的参数暴露在 URL 中,安全性比POST差一些

HTTP 请求的基本格式

  • <request line> 请求行
  • <headers> 请求头(参数头)
  • <blank line> 空白行
  • [<request-body>] 请求实体(GET没有, POST有

数据库

索引的分类

  主要分为聚集索引和非聚集索引:

  • 聚集索引存储记录物理上连续,而非聚集索引是逻辑上的连续,物理存储并不连续
  • 聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个

ResultSet 统计记录数目

  Java 中使用JDBC连接数据库,最后都会得到一个 ResultSet,比如如下的代码

Connection con = DriverManager.getConnection(url, username, password);
 Statement sta = con.createStatement();
 String sql = "select * from student";
 ResultSet resultSet = sta.executeQuery(sql);

  那么如何根据得到的ResultSet统计一共有多少条记录呢?注意:ResultSet没有提供类似size()length的 API 来直接获取总记录数。

  方法1:利用循环

  

int sum = 0;
while(resultSet.next()){
    sum++;
}

  方法2:利用ResultSet的getRow方法来获得ResultSet的总行数

  

resultSet.last(); //移到最后一行
int rowCount = resultSet.getRow(); //得到当前行号,也就是记录数

  

设计模式

  单例模式

   单例模式中必须保证只有一个实例存在。有时候单例是为了避免重复创建多个实例造成资源浪费,有时候也是为了避免多个不同的实例导致系统不一致的行为。

Android 中,App启动时系统会创建一个Application对象,用来存储系统的一些信息,这儿的Application 就是是单例模式的应用。可以通过Context.getApplicationContext()获取唯一的Application实例。

  

class Singleton {
    private volatile static Singleton instance;   

    private Singleton() { }   

    public static Singleton getInstance() {
        //第一重判断
        if (instance == null) {
            //锁定代码块
            synchronized (Singleton.class) {
                //第二重判断
                if (instance == null) {
                    instance = new Singleton(); //创建单例实例
                }
            }
        }
        return instance;
    }
}

  为什么synchronized里面需要加一次判断if (instance == null),是考虑这样的特殊情形:比如线程A、B都到达第一个if (instance == null),线程A进入synchronized代码中创建实例,线程B排队等待。但当A执行完毕时,线程B进入synchronized锁定代码,它并不知道实例已经创建,将继续创建新的实例,导致产生多个单例对象。

  也可以用内部类的方式创建,

  

public class Singleton(){
    private static class Inner {
        private static Singleton instance = new Singleton();
    }
    private Singleton() {
    }
    public static Singleton getInstance(){
        return Inner.instance;
    }
}

  

模板方法模式

在父类中实现一个算法不变的部分,并将可变的行为留给子类来实现。

比如AsyncTask 里面的四个方法onPreExecutedoInBackgroundonProgressUpdateonPostExecute

还有Activity也应用了模板方法模式
onCreateonStartonResumeonPauseonStoponDestroyonRestart

适配器模式

分为两种:类的适配器模式、对象的适配器模式

Android 里的 ListView 和 RecyclerViewsetAdapter()方法就是使用了适配器模式。

观察者模式

在 GUI 中,不管是 Windows 桌面应用、或者 Android、IOS,都会给某个按钮 Button 设置监听事件,这儿就是使用了观察者模式。Android 中设置 Button 的监听事件代码如下:

final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        // Perform action on click
    }
});

  

笔试编程题

关于线程和进程,不正确的描述是__。(选 D 栈是线程私有, 保存其运行状态和局部变量 )

A. 进程的隔离性要好于线程
B. 线程在资源消耗上通常要比进程轻量
C. 不同进程间不会共享逻辑地址空间
D. 同一个进程的线程之间共享内存,包括堆和栈
E. 进程间有途径共享大量内存中的数据
F. 线程间通讯可以通过直接访问全局变量,或者使用进程间通讯的机制(IPC)

找出未打卡的员工

题目:输入两行数据,第一行为全部员工的 id,第二行为某一天打卡的员工 id,已知只有一个员工没有打卡,求出未打卡员工的 id。(员工 id 不重复,每行输入的 id 未排序)
输入:
1001 1003 1002 1005 1004
1002 1003 1001 1004
输出:
1005

分析:可以用两个 List,第一个 List 保存所有员工的 id,第二个 List 保存打卡员工的 id,从第一个List 中把第二个 List 的数据都删除,最终剩下的就是未打卡员工的 id。

更好的方法:异或,两行数据中未打卡员工的 id 出现了一次,其余员工的 id 都出现了2次,两个相同的数异或为0。

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    while (scan.hasNext()) {

        String[] ids = scan.nextLine().split(" ");
        String[] marks = scan.nextLine().split(" ");
        int result = 0;
        for (int i = 0; i < ids.length; i++) {
            result ^= Integer.parseInt(ids[i]);
        }
        for (int i = 0; i < marks.length; i++) {
            result ^= Integer.parseInt(marks[i]);
        }
        System.out.println(result);
    }
}

  

手写代码题

快速排序

排序是经典面试题,公司也希望通过手写快排来考察面试者的编程习惯和基本功。

// 排序范围 [start, end], 包含 end
public void sort(int[] arr, int start, int end) {
    if (start < end) {
        int p = partition(arr, start, end);
        quickSort(arr, start, p - 1);
        quickSort(arr, p + 1, end);
    }
}
// 一次划分代码,返回被划分后的基准位置
public static int partition(int[] arr, int left, int right) {
    int pivot = arr[left];
    while (left < right) {
        while (left < right && arr[right] >= pivot)
            right--;
        if (left < right)
            arr[left++] = arr[right];
        while (left < right && arr[left] <= pivot)
            left++;
        if (left < right)
            arr[right--] = arr[left];
    }
    arr[left] = pivot;
    return left;
}

  Note:快排是不稳定的,常见的稳定排序是:冒泡、插入、归并

括号字符串是否合法

某个字符串只包括(,判断其中的括号是否匹配正确,比如(()())正确,((())()错误,不允许使用栈

这种类似题的常见思路是栈,对于左括号入栈,如果遇到右括号,判断此时栈顶是不是左括号,是则将其出栈,不是则该括号序列不合法。

面试官要求不能使用栈,可以使用计数器,利用int count字段。

public static boolean checkBrackets(String str) {
    char[] cs = str.toCharArray();
    int count = 0;
    for (int i = 0; i < cs.length; i++) {
        if (cs[i] == ‘(‘)
            count++;
        else {
            count--;
            if (count < 0) {
                return false;
            }
        }
    }

    return count == 0;
}

  

扑克牌随机发牌

对于52张牌,实现一个随机打算扑克牌顺序的程序。52张牌使用 int 数组模拟。

该算法的难点是如何保证随机性?有个经典算法shuffle,思路就是遍历数组,在剩下的元素里再随机取一个元素,然后再在剩下的元素里再随机取一个元素。每次取完元素后,我们就不会让这个元素参与下一次的选取。

To shuffle an array a of n elements (indices 0..n-1):
  for i from n − 1 downto 1 do
       j ← random integer with 0 ≤ j ≤ i
       exchange a[j] and a[i]

  注意这儿是0 ≤ j ≤ i,包括j=i的情况,因为可能洗牌后某个牌未发生交换,比如第51张牌还是原来的第51张牌。

public void randomCards() {
    int[] data = new int[52];
    Random random= new Random();
    for (int i = 0; i < data.length; i++)
        data[i] = i;

    for (int i = data.length - 1; i > 0; i--) {
        int temp = random.nextInt(i+1); //产生 [0,i] 之间的随机数
        swap(data,i,temp);
    }
}

  

智力题

金条付费

你让工人为你工作7天,回报是一根金条,这个金条平分成相连的7段,你必须在每天结束的时候给他们一段金条,如果只允许你两次把金条弄断,你如何给你的工人付费?

答案:切成一段,两段,和四段.

第1天: 给出1.
第2天: 给出2,还回1.
第3天: 给出1.
第4天: 给出4,还回1+2.
第5天: 给出1.
第6天: 给出2,还回1.
第7天: 给出1.

赛马

25匹马,速度都不同,但每匹马的速度都是定值。现在只有5条赛道,无法计时,即每赛一场最多只能知道5匹马的相对快慢。问最少赛几场可以找出25匹马中速度最快的前3名?

答案:

    • 25匹马分成5组,先进行5场比赛
    • 再将刚才5场的冠军进行第6场比赛,得到第一名。按照第6场比赛的名词把前面5场比赛所在的组命名为 A、B、C、D、E 组,即 A 组的冠军是第6场第一名,B 组的冠军是第二名 …
    • 分析第2名和第3名的可能性,如果确定有多于3匹马比某匹马快,那它可以被淘汰了。因为 D 组是第6场的第四名,整个D 组被淘汰了,同意整个 E 组被淘汰。剩下可能是整体的第2、3名的就是C组的第1名、B组的1、2名、A组的第2、3名。取这5匹马进行第7场比赛
      -所以,一共需要7场比赛
时间: 2024-12-28 01:38:54

互联网校招笔试题分享的相关文章

网易2018校招笔试题-数组能不能满足重排列后任意相邻的元素积都是4的倍数

今天看了一下网易最新的校招笔试题: 小易有一个长度为N的正整数数列A = {A[1], A[2], A[3]..., A[N]}.牛博士给小易出了一个难题:     对数列A进行重新排列,使数列A满足所有的A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍数.     小易现在需要判断一个数列是否可以重排之后满足牛博士的要求. 代码如下: 1 import java.util.Scanner; 2 3 /** 4 * Created by jy on 2017/9/9. 5

一位上了一个大的互联网公司笔试题分享

声明: 首先声明,我没有参加中考(我的老男人).我只是道听途说.这个测试题是否真的存在?谁知道! 在这一点,但想分享一些知识. 有关文字说明原来的问题: 给定一个二维数组,里面随机的填写0和1.求取把上下左右连续(斜线不算相连)的1周边0的个数. 在这里能够把由1构成数据看成一个岛屿,求岛屿海岸线的长度,即周边0的个数. 引子: 看过人机博弈-吃子棋游戏(二)算气的博友,应该瞬间就有思路了吧.事实上围棋的算气,在没有眼位的情况下,就是计算算实心岛屿的海岸线.在有眼位的情况下.围棋算气也是计算空心

2015年阿里巴巴校招笔试题

校招找工作的同学,可以看看,非常有帮助! 推荐: http://gointernetgo.com/textinterview/bishi-2015-alibba [产品经理]阿里巴巴2015校园招聘笔试题 [研发工程师]阿里巴巴2015校园招聘笔试题 [研发工程师]阿里巴巴2015校园招聘笔试题2 [国际安全运营专员]阿里巴巴2015校园招聘笔试题1 [产品运营]阿里巴巴2015校园招聘笔试题1 [前端开发工程师]阿里巴巴2015校园招聘笔试题1 [前端开发工程师]阿里巴巴2015校园招聘笔试题

一道某高大上互联网公司的笔试题分享

声明: 首先声明,我没有参加此次考试(吾老矣),我只是道听途说,是否真的存在这道试题呢?谁知道呢!在此仅仅是想向大家分享一些知识. 原题大概描述: 给定一个二维数组,里面随机的填写0和1,求取把上下左右连续(斜线不算相连)的1周边0的个数.在这里可以把由1构成数据看成一个岛屿,求岛屿海岸线的长度,即周边0的个数. 引子: 看过人机博弈-吃子棋游戏(二)算气的博友,应该瞬间就有思路了吧.其实围棋的算气,在没有眼位的情况下,就是计算算实心岛屿的海岸线.在有眼位的情况下,围棋算气也是计算空心岛屿内部的

兆易创新2016年9月校招笔试题_IC设计/验证

还有器件岗位的笔试题: 1.CMOS中哪些制造步骤中用到了离子注入,需要注意哪些?2.有哪些薄膜制备方法?各有什么优缺点?3.COMS的制作步骤,简要叙述.4.载流子的输运方式有哪些,简要叙述.5.半导体中缺陷种类,杂质的类型,缺陷杂质的危害,如何避免杂质缺陷.6.为何固体有超导体,导体,半导体,绝缘体?7.缓变PN结和突变PN结区别,如何制作,有何应用?8.CMOS的IV特性曲线,各个阶段的意义,如何让器件有效工作?9.质量测试中的加速失效作用.10.氧化层的击穿过程,如何避免击穿?附加题:N

小米2017校招笔试题

只过了20%...我日 树的高度 时间限制:C/C++语言 1000MS:其他语言 3000MS 内存限制:C/C++语言 65536KB:其他语言 589824KB 题目描述: 现在有一棵合法的二叉树,树的节点都是用数字表示, 现在给定这棵树上所有的父子关系,求这棵树的高度 输入 输入的第一行表示节点的个数n(1<=n<=1000,节点的编号为0到n-1)组成, 下面是n-1行,每行有两个整数,第一个数表示父节点的编号,第二个数表示子节点的编号 输出 输出树的高度,为一个整数 样例输入 5

2014年网易互联网在线笔试题一道

题目:有四个文件,每个文件中存有100万个int型整数,内存限制1M,该如何最优地得到四个文件的交集数,也就是在四个文件都出现的数的个数? 我的想法:因为内存限制1M,也就是1024*1024个字节,小于一个文件中所有数所占的存储100 0000*4,所以文件中的数没办法一次装到内存.采用外部排序.归并等方法实现. 具体: 1.最开始应该是对每个大文件进行外部排序,也就是n次从大文件中取出一部分数在内存中进行快速排序或堆排序,然后将结果存入小文件中,存入小文件的同时去重: 2.然后对n个小文件进

校招笔试题编程技巧总结

技巧一://统计字符串s1的频率 String s1 = in.nextLine(); //统计字符串s1的频率 for (char c1 : s1.toCharArray()) { if (hashMap1.containsKey(c1)) { hashMap1.put(c1, hashMap1.get(c1) + 1); } else { hashMap1.put(c1, 1); } } 技巧二:输入判断加 hasNext() Scanner scan=new Scanner(System.

网易2017年校招笔试题 最大的奇约数

题目: 定义函数f(x)为x的最大奇数约数,x为正整数,例如f(44) = 11. 现在给出一个N,需要求出f(1) + f(2) + f(3) + ... + f(N) 例如: N = 7 f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 7 = 21. 分析: 奇数的最大约数是自身, 偶数的最大约数是是除去所有偶因子之后的那个奇数.所以直观的思路就是挨个遍历一遍加起来. 代码: 1 #include <i