发布时间:2025-10-17 11:24:51    次浏览
有题在手,天下我有,要问从哪里得到的,我就不告诉你。今天,不是大牛专场,今天是给一些准备结束校园生活,的未来苦逼程序员的专场。既然是专场,那就来“愉快”的搬砖吧。 要问当代大学生的毕业前景,简单来说,毕业就等于失业。当你迷茫地离开朝夕相处的大学寝室,拖着行李无处可去的时候,请你别担心,你会发现,那些当初比你成绩好的大学同学,他们一样找不到工作。 大学生找工作,无非就那几种方式,网络简历,毕业双选会,还有直接去搬砖……还有一个,某些大学吧,他们有个什么校园招聘,就像小编前段时间去的那个,虽然是个坑,但也是校园招聘,至于里面有什么猫腻,就不再多说。对于我们这些调bug的,有能力就是最好的自我介绍,不管你的面试官如何刁难你,你只需要做一件事,把你给你出的什么招聘面试题给做出来,那你就八九不离十了。今天,小编为那些即将步入社会的毕业程序员,收集了近年来,互联网校园招聘的面试题,以供参考,考不考得到,我没法确定,但大致相似是可以确定的,毕竟考来考去,也就那几个。下面看正文,严肃的看……Java 一些知识点Object 有哪些方法 public 方法:getClass、equals、hashCode、toString、wait、notify protected 方法:clone、finalize private 方法:registerNatives,该方法作用是将不同平台C/C++实现的方法映射到Java中的native方法 publicclassObject{ privatestaticnativevoidregisterNatives(); // 声明后有紧接静态代码块 static{ registerNatives(); }} 自动装箱publicstaticvoidmain(String args) { inti = 0; Integer j = newInteger(0); System.out.println(j == i); System.out.println(j.equals(i));}上述代码的输出是true trueJava 虚拟机 GC 根节点的选择Java通过可达性分析来判断对象是否存活。基本思想是通过一系列称为”GC roots”的对象作为起始点,可以作为根节点的是: 虚拟机栈(栈帧中的本地变量表)中引用的对 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象 方法区中类静态属性引用的对象 方法区中常量引用的对象 作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表)中。虚拟机栈、本地方法栈这都是局部变量,某个方法执行完,某些局部使用的对象可以被回收。类加载机制 启动类加载器( Bootstrap ClassLoader)启动类加载器无法被 java 程序员直接引用, 这个类加载器负责把存放在JAVA_HOMElib目录中的, 或者被-Xbootclasspath参数指定路径中的, 并且是被虚拟机识别的类库加载到虚拟机内存中. 扩展类加载器(Extension ClassLoader)负责加载在JAVA_HOMElibext目录中的, 或者被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(Stringname, boolean resolve) throwsClassNotFoundException{ synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Classc = findLoadedClass(name); if(c == null) { long t0 = System.nanoTime(); try{ if(parent != null) { c = parent.loadClass(name, false); } else{ c = findBootstrapClassOrNull(name); } } catch(ClassNotFoundExceptione) { // 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); } returnc; }}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:利用循环intsum = 0; while(resultSet.next()){ sum++; }方法2:利用ResultSet的getRow方法来获得ResultSet的总行数resultSet.last(); //移到最后一行 introwCount = resultSet.getRow(); //得到当前行号,也就是记录数设计模式单例模式单例模式中必须保证只有一个实例存在。有时候单例是为了避免重复创建多个实例造成资源浪费,有时候也是为了避免多个不同的实例导致系统不一致的行为。Android 中,App启动时系统会创建一个Application对象,用来存储系统的一些信息,这儿的Application就是是单例模式的应用。可以通过Context.getApplicationContext()获取唯一的Application实例。classSingleton{ privatevolatilestaticSingleton instance; privateSingleton() { } publicstaticSingleton getInstance() { //第一重判断 if(instance == null) { //锁定代码块 synchronized(Singleton.class) { //第二重判断 if(instance == null) { instance = newSingleton(); //创建单例实例 } } } returninstance; } }为什么synchronized里面需要加一次判断if (instance == null),是考虑这样的特殊情形:比如线程A、B都到达第一个if (instance == null),线程A进入synchronized代码中创建实例,线程B排队等待。但当A执行完毕时,线程B进入synchronized锁定代码,它并不知道实例已经创建,将继续创建新的实例,导致产生多个单例对象。也可以用内部类的方式创建,publicclass Singleton(){ privatestaticclassInner{ privatestaticSingleton instance = newSingleton(); } privateSingleton() { } publicstaticSingleton getInstance(){ returnInner.instance; }}模板方法模式在父类中实现一个算法不变的部分,并将可变的行为留给子类来实现。比如AsyncTask里面的四个方法onPreExecute、doInBackground、onProgressUpdate、onPostExecute还有Activity也应用了模板方法模式onCreate、onStart、onResume、onPause、onStop、onDestroy、onRestart适配器模式分为两种:类的适配器模式、对象的适配器模式Android 里的 ListView和 RecyclerView的setAdapter()方法就是使用了适配器模式。观察者模式在 GUI 中,不管是 Windows 桌面应用、或者 Android、IOS,都会给某个按钮 Button 设置监听事件,这儿就是使用了观察者模式。Android 中设置 Button 的监听事件代码如下:finalButton button = (Button) findViewById(R.id.button_id);button.setOnClickListener(newView.OnClickListener() { publicvoidonClick(View v) { // Perform action on click }});笔试编程题线程 VS 进程关于线程和进程,不正确的描述是__。(选 D 栈是线程私有, 保存其运行状态和局部变量 )A. 进程的隔离性要好于线程B. 线程在资源消耗上通常要比进程轻量C. 不同进程间不会共享逻辑地址空间D. 同一个进程的线程之间共享内存,包括堆和栈E. 进程间有途径共享大量内存中的数据F. 线程间通讯可以通过直接访问全局变量,或者使用进程间通讯的机制(IPC)找出未打卡的员工题目:输入两行数据,第一行为全部员工的 id,第二行为某一天打卡的员工 id,已知只有一个员工没有打卡,求出未打卡员工的 id。(员工 id 不重复,每行输入的 id 未排序)输入:1001 1003 1002 1005 10041002 1003 1001 1004输出:1005分析:可以用两个 List,第一个 List 保存所有员工的 id,第二个 List 保存打卡员工的 id,从第一个List 中把第二个 List 的数据都删除,最终剩下的就是未打卡员工的 id。更好的方法:异或,两行数据中未打卡员工的 id 出现了一次,其余员工的 id 都出现了2次,两个相同的数异或为0。publicstaticvoidmain(String args) { Scanner scan = newScanner(System.in); while(scan.hasNext()) { String ids = scan.nextLine().split(' '); String marks = scan.nextLine().split(' '); intresult = 0; for(inti = 0; i ids.length; i++) { result ^= Integer.parseInt(ids[i]); } for(inti = 0; i marks.length; i++) { result ^= Integer.parseInt(marks[i]); } System.out.println(result); }}手写代码题快速排序排序是经典面试题,公司也希望通过手写快排来考察面试者的编程习惯和基本功。// 排序范围 [start, end], 包含 endpublicvoid 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); }}// 一次划分代码,返回被划分后的基准位置publicstaticint 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; returnleft;}Note:快排是不稳定的,常见的稳定排序是:冒泡、插入、归并。括号字符串是否合法某个字符串只包括(和),判断其中的括号是否匹配正确,比如(()())正确,((())()错误,不允许使用栈。这种类似题的常见思路是栈,对于左括号入栈,如果遇到右括号,判断此时栈顶是不是左括号,是则将其出栈,不是则该括号序列不合法。面试官要求不能使用栈,可以使用计数器,利用int count字段。publicstaticbooleancheckBrackets(String str) { char cs = str.toCharArray(); intcount = 0; for(inti = 0; i cs.length; i++) { if(cs[i] == '(') count++; else{ count--; if(count 0) { returnfalse; } } } returncount == 0;}扑克牌随机发牌对于52张牌,实现一个随机打算扑克牌顺序的程序。52张牌使用 int数组模拟。该算法的难点是如何保证随机性?有个经典算法shuffle,思路就是遍历数组,在剩下的元素里再随机取一个元素,然后再在剩下的元素里再随机取一个元素。每次取完元素后,我们就不会让这个元素参与下一次的选取。To shuffle an array a ofn elements (indices 0..n-1): fori fromn ? 1 downto 1 doj ← random integer with0 ≤ j ≤ i exchange a[j] and a[i]注意这儿是0 ≤ j ≤ i,包括j=i的情况,因为可能洗牌后某个牌未发生交换,比如第51张牌还是原来的第51张牌。publicvoidrandomCards() { int data = newint[52]; Random random= newRandom(); for(inti = 0; i data.length; i++) data[i] = i; for(inti = data.length - 1; i 0; i--) { inttemp = 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场比赛 差不多就这些了,未来是继续当一个调bug的,还是回家当一个啃老族,就看面试官出的是什么题了,不说了。工头又拉了两车砖来了。 了解野狗,点击阅读原文“报名”