目录

  • 背景
  • 题目
    • 1、Object的常用方法
    • 2、 == 和 equals 的区别是什么?
      • ==
      • equals
    • 3、以下代码的运行结果
    • 4、以下代码的运行结果
    • 5、String, StringBuilder,StringBuffer
    • 6、ArrayList和LinkedList
    • 7、一些常用的线程安全的集合类
    • 8、以下代码的运行结果
    • 9、完成下面的代码
    • 10、写一个线程安全的单例模式
    • 11、哪些方法保障线程安全
      • 使用synchronized关键字
        • 同步代码块
        • 同步方法
      • 使用lock
    • 12、算法,任选一个
    • 13、数据库编程
      • 统计每个班级(class_id)的人数
      • 查询所有18岁以上学生的信息。如果有课程成绩,查询出最高分的课程成绩
      • 查询每门课程最高分的学生信息
    • 14、介绍下几种join
    • 15、基本类型和包装类型的区别

背景

21年4月,应聘杭州滨江某自研公司,以下是该公司的笔试题
题目的答案,是根据我的理解写的。可能有不对的地方,欢迎大家指正。
这一场的面试题忘了,当时没记录

题目

1、Object的常用方法

●1.getClass()

public final native Class<?> getClass()

获取对象运行时的class对象,通常和反射机制搭配使用。
class对象就是描述对象所属类的对象
●2.hashCode

public native int hashCode()

获取对象的散列值。Object中该方法默认返回的是对象的堆内存地址。
●3.equals

public boolean equals(Object object){return (this == obj);
}

比较2个对象,如果2个对象引用的是同一个对象,那么返回true。
一般equals和==是不一样的,但在Object中是一样的。子类一般重写equals方法。
●4.clone

protected native Object clone() throws CloneNotSupportedException;

该方法是保护方法,实现对象的浅拷贝,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportException。
默认的clone是浅拷贝。浅拷贝,指的是对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存。
深拷贝就是会连引用的对象也重新创建。
●5.toString

public String toString(){return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

返回一个String对象,一般子类都有覆盖。
默认返回格式:对象的class名称 + @ + hashCode的十六进制字符串。
●6.notify

 public final native void notify()

final方法,主要唤醒在该对象上等待的某个线程
●7.notifyAll

 public final native void notifyAll()

final方法,唤醒在该对象上等待的所有线程
●8.wait(long timeout)

 public final native void wait(long timeout) throws InterruptedException

timeout是毫秒值
使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。
这里设置一个超时间隔,如果在规定时间没有获得到锁就返回。
无参的wait() 方法会一直等待,直到获得锁或者被中断。
●9.wait(long timeout, int nanos)

 public final void wait(long timeout, int nanos) throws InterruptedException{if (timeout < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {timeout++;}wait(timeout);}

timeout:最大等待时间,毫秒
nanos:附加时间在毫秒范围(0-999999),纳秒/毫微秒,十亿分之一秒
该方法导致当前线程等待,直到其他线程调用此对象的 notify() 方法或notifyAll()方法,或在指定已经过去的时间。此方法类似于 wait 方法的一个参数,但它允许更好地控制的时间等待一个通知放弃之前的量。实时量,以毫微秒计算,计算公式如下:1000000 * timeout + nanos
在所有其他方面,这种方法与 wait(long timeout) 做同样的事情。特别是 wait(0, 0) 表示和 wait(0) 相同。
●10.wait()

 public final void wait() throws InterruptedException{wait(0);
}

实际调用的是wait(long timeout)方法,只不过timeout是0。
●11.finalize

 protected void finalize() throws Throwable{}

是保护方法,用于在GC的时候再次被调用。如果实现了这个方法,对象可能在这个方法中再次复活,避免被GC回收。

2、 == 和 equals 的区别是什么?

==

对于基本类型和引用类型 == 的作用效果是不同的,如下所示:
基本类型:比较的是值是否相同;
引用类型:比较的是引用是否相同;
代码示例:

String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true

代码解读:
因为 x 和 y 指向的是同一个引用,所以 == 也是 true。
而 new String()方法则重写开辟了内存空间,所以 == 结果为 false,
而 equals 比较的一直是值,所以结果都为 true。

equals

equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。看下面的代码就明白了。
首先来看默认情况下 equals 比较一个有相同值的对象,代码如下:

String s1 = new String("老王");
String s2 = new String("老王");
System.out.println(s1.equals(s2)); // true

进入 String 的 equals 方法,找到了答案,代码如下:

public boolean equals(Object anObject) {    if (this == anObject) {        return true;   }    if (anObject instanceof String) {        String anotherString = (String)anObject;        int n = value.length;        if (n == anotherString.value.length) {            char v1[] = value;           char v2[] = anotherString.value;            int i = 0;            while (n-- != 0) {                if (v1[i] != v2[i])                    return false;                i++;            }            return true;        }    }    return false;
}

可以看出, String 重写了 Object 的 equals 方法,把引用比较改成了值比较。
总结 :
== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;
equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,
所以一般情况下 equals 比较的是值是否相等。

3、以下代码的运行结果

public class Stu {private String name;private int age;public Stu(String name, int age) {super();this.name = name;this.age = age;}public static void main(String[] args) {Stu s1 = new Stu("张三", 18);Stu s2 = new Stu("张三", 18);System.out.println(s1 == s2);// falseSystem.out.println(s1.equals(s2));// false}
}

4、以下代码的运行结果

String s0 = null;
String s1 = "Tomcat";
String s2 = "Tom" + "cat";
String s3 = new String("Tomcat");
System.out.println(s1==s2);//true
System.out.println(s1.equals(s2));//true
System.out.println(s1==s3);//false
System.out.println(s1.equals(s3));//true
//intern():返回常量池中这个对象的引用
System.out.println(s1==s3.intern());//true
System.out.println(s0==s1);//false
System.out.println(s0.equals(s1));//空指针异常!
//null去equals某个值,就会报错。如果非null去equals任意值,就不会错,如下所示
System.out.println(s1.equals(s0));//false

5、String, StringBuilder,StringBuffer

String:定义的不可变字符串。在操作少量数据时使用。
StringBuilder:定义的可变字符串。线程不安全。性能比StringBuffer快。推荐单线程下使用。
StringBuffer:定义可变字符串。线程安全,因为它的所有公开方法都用synchronized修饰。推荐多线程下用。
整体性能上:StringBuilder > StringBuffer > String
为什么是这样的性能排序?
String每执行一次+(重载运算符),就要创建一个新的对象
StringBuffer比StringBuilder相比,少了同步锁。
为什么不可变?
String底层代码中,整个类被final修饰,该类不能被继承;其中的value[]属性被final修饰,引用不能被修改。
为什么StringBuffer线程安全?
StringBuffer通过synchronized关键字修饰,保证资源不会被抢,从而确保了线程安全。

6、ArrayList和LinkedList

①ArrayList底层是数组,(动态数组),LinkedList底层是双向链表。
②随机访问get和set,ArrayList要优于LinkedList。
③对于新增和删除,add/remove,LinkedList更快,因为ArrayList要移动数据。

7、一些常用的线程安全的集合类

①Vector:(实现了List接口),比ArrayList多了同步化机制
②Stack:栈,继承于Vector。先进后出。
③HashTable:比HashMap多了线程安全。(实现了Map接口)
④ConcurrentHashMap:高效且线程安全的集合。(继承AbstractMap,实现了ConcurrentMap接口)

8、以下代码的运行结果

static class VO implements Cloneable {List<Object> datas = new ArrayList<>();@Overridepublic VO clone() throws CloneNotSupportedException {return (VO) super.clone();}
}@Test
public void cloneT() throws CloneNotSupportedException {VO vo = new VO();vo.datas.add("1");VO vo2 = vo.clone();vo2.datas.add("2");System.out.println(vo.datas.size());// 2System.out.println(vo2.datas.size());// 2
}

9、完成下面的代码

public class VO {private Integer id;public VO(Integer id) {super();this.id = id;}//...get、set、toString方法
}List<VO> volist = mockDatas();

要求:请对集合voList,根据id进行分组
分析:就是有个集合,集合内装的是某种对象(泛型),对象有个ID字段。
根据ID进行分组,同个ID的对象放在一起。
实现代码如下

public static void main(String[] args) {// 根据题意,准备的测试用的voListVO v1 = new VO(18);VO v2 = new VO(18);VO v3 = new VO(18);VO v4 = new VO(18);List<VO> voList = new ArrayList<>();voList.add(v1);voList.add(v2);voList.add(v3);voList.add(v4);//解法1// 0.新建map,存放分组后的vo集合数据Map<Integer, List<VO>> map = new HashMap<Integer, List<VO>>();// 1.遍历listfor (VO vo: voList) {// 2.获取每个元素的id,判断map中的key有没有这个idif (map.containsKey(vo.getId())) {// 有,就把这个元素放到这个key下的value里map.get(vo.getId()).add(vo);} else {// map的key里没有这个id,// ==>那就以此新建key,再把对应的vo集合放进valueList<VO> newVOList = new ArrayList<VO>();newVOList.add(vo);map.put(vo.getId(), newVOList);}}// 现在,已经得到了按id分组的map。// 下一步,根据map,新建list,把分好组的数据放进去List<List<VO>> resultList = new ArrayList<List<VO>>(map.values());// 展示结果for (List<VO> list : resultList) {for (VO vo : list) {System.out.println("User---" + vo.toString());}}/** HashMap.values(): 获取value集合* 把Map转换成List<List<User>>,为什么会变成List<List<User>>?* 原因在于* map是以多个userId为键值,存储多个List<User>,map.values转换成list就会变成* List<List<User>>*/// 解法2——使用Stream流Map<Integer, List<VO>> finalMap = voList.stream().collect(Collectors.groupingBy(VO::getId));
}

10、写一个线程安全的单例模式

单例模式,一种设计模式,一个类只能创建一个对象。
单例模式,可以有饿汉式 和 懒汉式。其中饿汉式,是线程安全的。
懒汉式:
(1)为节省内存,创建对象的步骤放到getInstance()中
(2)为保证单例,创建对象时加判断。若未创建,就创建;若已创建,就返回之前创建的
(3)为线程安全,方法上加锁,用synchronized上锁

//处理后的懒汉式(线程安全), 缺点效率低,
public static Singleton{private static Singleton singleton;private Singleton(){}public static synchronized Singleton getInstance(){if(singleton == null){singleton = new Singleton();}return singleton;}
}
//没有用synchronized 的懒汉式, 线程不安全
public static Singleton{private static Singleton singleton;private Singleton(){}public static Singleton getInstance(){if(singleton == null){singleton = new Singleton();}return singleton;}
}

饿汉式
(1)私有化构造器
(2)内部创建一个实例
(3)定义一个方法将实例返回。
这个方法的修饰符必须是public static,返回对象也static修饰。
(4)返回对象用private修饰,防止外界随意调用。

//饿汉式
public class Singleton{private static Singleton singleton = new Singleton();private Singleton(){    }public static Singleton getInstance(){return singleton;}
}

11、哪些方法保障线程安全

使用synchronized关键字

同步代码块

synchronized 锁对象{
多条操作共享数据的语句
}
锁对象:任意对象,多个线程必须使用同一把锁
这种方法的好处:多线程下提高安全性
坏处:运行速率变低

同步方法

●同步非静态方法:
格式:将synchronized写在方法上。
锁对象:当前类对象this
●同步静态方法:
锁对象:当前的类对象,类名.class

使用lock

lock():加锁 unlock():解锁
一般使用ReturnLock,是lock的实现类。
即,Lock lock = new ReturnLock
释放锁必须在finally中执行,因为锁必须释放

12、算法,任选一个

(1)合并2个有序数组,写出代码实现
(2)从一个有序数组中找一个缺少的元素。数组中至少有一个缺失元素。如数组[1,2,4,5,6,7,],缺少数字3

13、数据库编程

学生表stu(id,name,age,class_id)
学生的成绩表score(id,stu_id,kemu,chengji)

统计每个班级(class_id)的人数

select class_id as '班级', count(id) as '人数'
from stu
group by class_id

查询所有18岁以上学生的信息。如果有课程成绩,查询出最高分的课程成绩

select stu.*, score.kemu, score.chengji
from stu stu
left join score
on stu.id = score.stu_id
where stu.age > 18

查询每门课程最高分的学生信息

 select b.kemu,b.chengji, c.age, c.name from (select kemu, max(chengji) maxc from score group by kemu) a,score b, stu c where a.kemu = b.kemu and a.maxc = b.chengji andb.stu_id = c.id

14、介绍下几种join

15、基本类型和包装类型的区别

(1)包装类型可以为null,基本类型不可以
使得包装类型可以应用于POJO中,而基本类型不行。
(2)包装类型可用于泛型,基本类型不可以
(3)基本类型比包装类型更高效
基本类型在栈中存储具体的数值。包装类型存储的是堆中的引用.
(4)自动装箱和自动拆箱
基本类型 -> 包装类型,自动装箱
包装类型 -> 基本类型,自动拆箱

21年-自研-笔试题相关推荐

  1. 2.2 华为-软件工程师-7.21笔试题

    文章目录 2.2 华为-软件工程师-7.21笔试题 2.2.1 编程一:资源占用 2.2.2 编程二:贪心+小根堆 2.2.3 编程三:图 2.2 华为-软件工程师-7.21笔试题 2.2.1 编程一 ...

  2. Java 学习(21)--集合笔试题

    集合笔试题 1.产生10个1-20之间的随机数,要求随机数不能重复(List 和 Set 分别实现) 分析:1.创建一个 ArrayList 对象 2.如果 ArrayList 对象长度小于 10 3 ...

  3. 【阿里21校招笔试题】【日常生活】【BUG日记】我真是个呆瓜!居然不会写冒泡排序了,我吐了!结果阿里的校招笔试题一题都没做好!!!我人真的傻了!就卡在排序上!!!

    [记录]:记录一次呆瓜日记,自己真是一个大傻子. [经过]:今天晚上在做阿里校招的笔试题的时候,我人傻了.固定一个小时,做两道编程题,结果第一题都没做完. [题1]:(只记得大概需求)输入一个数n,再 ...

  4. 转贴:雅虎公司C#笔试题,看看你能解答多少

    这是刚在在网上看到了,觉得这些题目出得真不错,能考出一个程序员的基本功.所以先发在这里,做个备份,以后慢慢来做(偶好像只能免强及格哦,呵呵,关于网络的题目太多了,偶不太熟啊)- ----------- ...

  5. 迭代器笔试题,看看你会不会?

    有位小朋友最近正在为年后换工作做准备,但是遇到一个问题,觉得很不可思议的一道笔试题.然后我把这道题发到技术群里,发现很多人居然不知道,很多都是连蒙带猜的说.感觉很有必要写一篇文章来说道说道. 有位小朋 ...

  6. java 用程序代码解释继承_关于初级java程序员笔试题

    关于初级java程序员笔试题 Sun 认证Java程序员考试内容涉及Java所有相关知识.编程概念及applet开发技巧.下面是小编整理的关于初级java程序员笔试题,欢迎大家参考! 第一题:判断题 ...

  7. php mysql技术笔试题_PHP面试笔试题--选择题部分(最新整理)

    <PHP面试笔试题--选择题部分(最新整理)>由会员分享,可在线阅读,更多相关<PHP面试笔试题--选择题部分(最新整理)(7页珍藏版)>请在人人文库网上搜索. 1.1. 以下 ...

  8. 机器学习笔试题精选(二)

    https://blog.csdn.net/red_stone1/article/details/81023976 上次 机器学习笔试题精选(一)中,我们详细解析了机器学习笔试 15 道题.今天,红色 ...

  9. Java面试笔试题大汇总一(最全+详细答案)

    Java面试笔试题大汇总二(最全+详细答案)https://www.jianshu.com/p/f5120f1b75be Java面试笔试题大汇总三(最全+详细答案)https://www.jians ...

最新文章

  1. 领歌leangoo敏捷工具个人工作台功能
  2. linux修改权限重启恢复,Linux错误执行:chmod 777 .*或chown -R * 的补救方法
  3. 【电信增值业务学习笔记】10基于业务节点的增值业务提供技术
  4. 什么是“ rpcsvchost”,以及为什么它在Mac上运行?
  5. AspNetPager 修改 然后返回当前页
  6. Java多线程学习十:线程池实现“线程复用”的原理
  7. vim配置c语言开发环境变量,gcc配置和vim编程
  8. 卷积神经网络CNN算法原理
  9. java a =a-=aa_java 初学 :求 s=a+aa+aaa+aaaa+aa...a 的值,其中 a 是一个数字。几个 数相加由键盘控制。...
  10. 【Python实例第17讲】均值偏移聚类算法
  11. C++二叉树遍历递归算法
  12. VNPY_IB API封装
  13. android手机免费无线投屏电脑方法教程步骤AirServer7
  14. 滑动窗口协议如何实现流量控制
  15. 大数据之Kafka介绍
  16. kappa一致性检验教程_Kappa一致性检验:两种诊断方法的结果是否一致?
  17. mysql的组内排序生成序号_sql 分组查询,组内排序, 组内添加序号 (SQL Server 排序函数 ROW_NUMBER和RANK 用法总结)...
  18. 74ls163是同步清零吗_74LS163是具有同步清零功能的十六进制计数器,要
  19. 安装Office 2016时报错Office 16 Click-to-Run Extensibility Component的处理办法
  20. MyBatis9.28 + jdk1.8+Mysql 5.7

热门文章

  1. CCNP的考试是中文还是英文?
  2. 2021年保研预推免经验贴
  3. deeplearning课程学习报告(1)
  4. UE 虚幻引擎(不同材质发出不同脚步声)
  5. QT Creator 快速入门教程 读书笔记
  6. 微信公众号开发——服务器配置
  7. java下载文件名称各种浏览器兼容问题
  8. python伪造浏览器请求头_python浏览器伪装
  9. 2022/01/10 老男孩带你21周Go语言 (十四)
  10. 11.27 学习闲聊