java面试笔试考点(一)
文章内容输出来源:拉勾教育大数据实训营中的预科知识
作为今年的应届毕业生,由于本科专业不是java相关的专业,但是平时也想着去学习一下java相关的知识,然而自己学习总是不够透彻,于是决定要系统的学习一些东西,并且把以前的基础全都补一遍!经过两个月的学习,事实证明当初的选择是正确的,通过这次在 Java 预科班的“回炉重造”(不得不说这两个月时间的预科内容是真的十足!根本来不及休息,课后作业量也是非常的精!),最近,老师给的内推机会,不管最后成功与否,都是我宝贵的经验.
下面是这次面试提到的问题:(可能由于我简历中没有什么内容和应届生的身份,所以面试官问得问题还是比较基础的,如有差错请各位大佬们纠正指错!)
反射相关
面试官:给你一道题:有一个字符串str="a.b.c" ,现在你已知的是一个Class X{} 其中有一个成员变量为A a; 而在Class A中,有一个成员变量B b;B中有一个成员变量C c;问你,怎么从X当中获取c的getC的方法或者获取其中的成员变量的值?(默认每个类中都会有对应的get set方法)
class X{
A a;
}
class A{
B b;
}
class B{
C c;
}
class c{
int c=2;
无参构造和有参构造
get 和 set方法
}
我:嗯?
我:emmm,让我一步一步来试试看,首先先获得这几个类的变量名称,字符串是str="a.b.c",所以进行字符串的切割
面试官:可以,写一下代码
我:好嘞
String[] split= str.split(".")
面试官:嗯,你自己来看看这段代码有什么问题?
我:emmmm
面试官(面带微笑):split切割,里面的参数要求是什么?
我:里面要求的是正则表达式,用"."进行切割,没..问题吧?
面试官:那我问你,正则表达式有哪些特殊形式?
我: d 表示任意一个数字,相当于[0-9]
D 表示任意非数字字符
s 空白字符,相当于[tnx0Bfr]
S 非空白字符
w 任意一个单词字符,相当于[a-zA-Z_0-9]
W 任意一个非单词字符
面试官:嗯...还有么?给你个提示 如果要表示换行的话,怎么写
我: "n"
面试官:嗯.. 那这里切分的.有没有特殊含义呢?
我:!!!∑(゚Д゚ノ)ノ 哦哦哦,正则表达式中 . 代表的是任意一个字符(通常不包含换行符)
面试官:那知道问题出在哪里了么?
我:明白了!
String[] split = str.split(".");
//顺便复习一下如何输出数组
//传统for循环方式
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
//第二种for each循环
for (String s :split) {
System.out.println(s);
}
//利用Array类中的toString方法
System.out.println(Arrays.toString(split));
面试官:那么就继续吧,你已经得到了三个类中的成员变量名字了,继续
我:因为已知的是X x{} 利用反射获取X.class 再利用方法获得[成员类型 成员变量][A a],因为这道题里面每一个类中只有一个成员变量,简单的就取获得到的Filed[]中第一个就是他的类名称,然后利用getType()获取A.class,然后再获取A中的[成员类型 成员变量][B b],以此类推获得C中的成员变量.再利用C.class来获取对应的无参构造方法并创建对象,接着就可以获取到对应的成员方法.然后调用invoke方法获取到C中成员变量d的值
Class<X> xClass = X.class;
System.out.println(xClass);//class com.test.reflection.X
Field[] declaredFields = xClass.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields));//[com.test.reflection.A com.test.reflection.X.a]
Class<?> typeA = declaredFields[0].getType();
System.out.println(typeA);//class com.test.reflection.A
Field[] declaredFields1 = typeA.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields1));//[com.test.reflection.B com.test.reflection.A.b]
Class<?> typeB = declaredFields1[0].getType();
System.out.println(typeB);//class com.test.reflection.B
Field[] declaredFields2 = typeB.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields2));//[com.test.reflection.C com.test.reflection.B.c]
Class<?> typeC = declaredFields2[0].getType();
System.out.println(typeC);//class com.test.reflection.C
Field[] declaredFields3 = typeC.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields3));//[int com.test.reflection.C.d]
//获取c的成员方法
// 根据Class对象来获取对应的无参构造方法
Constructor<?> constructor = typeC.getConstructor();
// 使用无参构造方法构造对象并记录
Object o = constructor.newInstance();
//根据Class对象来获取对应的成员方法
Method getDS = typeC.getMethod("getC");
Object invoke = getDS.invoke(o);
System.out.println("c中的值为:"+invoke);
面试官(面无表情):嗯,这样确实可以实现.在获取对应的成员方法这一块,如果不直接写getC,让你自己从你切割的内容中如何写getC
我:那就拼接字符串,获取切割中的最后一个元素,将其转换成大写然后与get进行拼接
String s = split[split.length - 1].toUpperCase();
StringBuilder sb=new StringBuilder("get");
sb.append(s);
System.out.println(sb.toString());
Method getDS = typeC.getMethod(sb.toString());
Object invoke = getDS.invoke(o);
System.out.println("c中的值为:"+invoke);//c中的值为:2
面试官:嗯 好 那我们接着来
我:ε=(´ο`*))) 好嘞好嘞
求斐波那契(Fibonacci)数列的第 n
项
面试官:求一下斐波那契数列的第n项和
我:斐波那契F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 N > 1.这里可以用递归
public static int fib(int i) {
if(i==0){
return 0;
}
if(i==1){
return 1;
}
return fib(i - 1) + fib(i - 2);
}
面试官:嗯,可以 但是如果这样做的话会出现什么问题?
我:如果使用递归的话,当i数值很大的时候,会出现大量的已经计算过的内容,产生了冗余
面试官:那如何解决冗余呢?
我:那就用map数组将每一次计算到的数值进行存储,然后再用到的时候将其取出来
public static int fib(int n) {
return fib(n, new HashMap());
}
public static int fib(int n, Map<Integer, Integer> map) {
int constant = 1000000007;
if (n < 2)
return n;
if (map.containsKey(n))
return map.get(n);
int first = fib(n - 1, map) % constant;
map.put(n - 1, first);
int second = fib(n - 2, map) % constant;
map.put(n - 2, second);
int res = (first + second) % constant;
map.put(n, res);
return res;
}
面试官:那这样做,是什么换了什么呢?
我:是用空间换时间,多增加了一个map的存储空间,减少计算时间
面试官:嗯,好的,你再用另外一种方法写一下
我:那就用循环求余的方式吧
int a = 0, b = 1, sum;
for(int i = 0; i < n; i++){
sum = (a + b) % 1000000007;
a = b;
b = sum;
}
return a;
排序
面试官:下面是排序问题,用代码写出排序,无论是冒泡排序,还是插入排序
我:好的(这方面知识就比较基础而且网上的教学很多,在这里就不展示了)
可以搜索
注解
面试官:说一下元注解有哪些?并说一下其中一个的编译阶段和运行阶段是什么样的?
我:(阿巴阿巴)
总结
通过这次面试,深深的感觉到了自己还有很多不足,还需要继续努力!总结一下这次面试所涉及到的知识点:
1.反射相关知识
2.split参数中正则表达式的应用
3.斐波那契数列所引出的递归思想 动态规划和时间/空间复杂度
4.十大经典排序算法
5.注解相关知识