黑马程序员技术交流社区

标题: [哈尔滨校区]对于常见面试问题小记_1 [打印本页]

作者: 朱龙华    时间: 2017-12-14 00:04
标题: [哈尔滨校区]对于常见面试问题小记_1
本帖最后由 朱龙华 于 2017-12-14 08:18 编辑

[size=10.5000pt]引言:学了几个月的java,收获很大,经历很多,从认识这个物质世界到进入电脑语言的世界,从世界上第一台计算机到互联网时代,世界在一步步缩小,而人也在一步步进步。学习java这段时间,对于我这种入行不久的小白来说,首选计算机语言java还是不错的,可能对于一些老程序员来说学习这些东西如鱼得水,时常阅读到大神讲述自己经历的时候,语言的概述都是一笔带过,很大一部分是把这些语言和一些框架结合,作为工具来写它们是这么帮助自己完成需求的,在我看来,他们在比我们资源缺乏的时代走到现在这一步,除了自身的毅力之外,也因为他们养成了很好的学习习惯,即使轻描淡写,依然让我感到敬畏,可以这么说,没有老一辈,就没有巨人的肩膀在我们面前。
[size=10.5000pt]从我学习的角度看,年轻人嘛,接收新事物的能力是不错,但是有句话说的好,好记性不如烂笔头,巨人也是从跬步开始滴,所以很早就开始做笔记,也一直坚持下来,收获挺多的,马上学完框架了,回顾了一下之前的内容,发现自己记录了一些老师或者同学们提到过的面试题,今天总结了一下,发上来大家一起参考吧,好东西,得用对地方。
[size=10.5000pt]其实另外我还想补充一点,我觉得最基本的,你在简历中写的那些你会的技术,最起码的在你脑中需要知道它是什么,有什么作用,有什么案例我可以使用,如果你给我需求我可以使用什么技术去解决,这样才能让别人相信你确实会这个技术,而不是课堂讲了,在你的认知中就会了,两者是不等价的,所以每当学习或使用一门技术时,带着问题去学,学完了多问问自己,这样才会对编程有大纲式思维,以后没有老师教,也可以自己学。
[size=10.5000pt]言归正传,开始一轮小面试,其中要自己脑补相关的问题,毕竟文章是死的,人是活的 - -
[size=10.5000pt]
1. 最近老师们都说很多面试之前需要手写JDK动态代理,这里我总结了一下,还扩展了CGLIB动态代理(扩展的看看就行)
/**
* 这是通用版JDK动态代理的模板类
*                 1.接收目标对象,并扩大它的作用范围(声明到成员位置)
*                 2.写一个方法去返回代理对象         return Proxy.newProxyInstance(三个参数)
*                 3.方法中第三个参数是代理接口InvocationHandler对象,这个对象种又有一个方法invoke(三个参数)来实现方法增强
* 实现JDK动态代理可以有两种方法
*                 1.可以使用匿名内部类的方式做
*                 2.为了代码的整洁,这里使用实现invocationHandler接口的方式来实现
* @author zlh
*/

// 5.本类实现InvocationHandler接口
public class ProxyFactory implements InvocationHandler {
        // 2.将目标对象的作用范围扩大到全类
        public Object target;
        // 1.接收目标对象(需要代理的对象),使用有参构造
        public ProxyFactory(Object target) {
                this.target = target;
        };

        // 3.创建一个方法返回动态代理实例(注意:这里不能使用静态修饰,因为我们的target目标对象是通过有参构造传递过来,如果直接静态调用就出错了)
        public Object createProxy() {
                // 4.使用JDK提供的代理类创建 方法实现代理
                return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }

        // 6.重写invoke方法
        // 返回值是Object
        // 参数列表是:代理对象Object proxy,目标对象的方法 Method method,方法的参数Object[] args
        // 此处记得抛出异常
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 7.这里可以对切入点cart point和通知advice进行操作
                System.err.println("切入点cart point和通知advice进行操作...");

                // 8.调用我们原先的业务逻辑,执行
                return method.invoke(target, args);
        };
}

====


/**
* 使用cglib代理进行目标对象的增强
*                 1.有参构造接收目标对象,并扩大作用范围
*                 2.创建方法返回CGLIB代理对象,里面使用Enhancer对象进行设置
*                 3.创建enhancer增强者对象
*                 3.
* @author zlh
*/
public class CglibProxyFactory implements MethodInterceptor{
        //1.接收目标对象并扩大作用域
        private Object target;
        public CglibProxyFactory(Object target) {
                this.target=target;
        }

        /**
         * 总体来说返回代理对象有两种解决方式:
         * 一:傻瓜式,一步步来
         *                 1.创建Enhancer增强者对象
         *                 2.设置目标对象类型(target.class)
         *                 3.设置回调对象类型(Callback接口)
         *                 4.执行create()方法并返回
         * 二:直接使用Enhancer有参构造传递目标类和代理对象类型
         * @return
         */
        //2.创建方法返回CGLIB代理对象,还是要注意因为这里使用的是传参,所以不能使用static
        public Object createCglibProxy(){
                //2.1这里一个增强器进行增强Enhancer
                Enhancer enhance = new Enhancer();

                        //2.2设置目标对象的类型
                        //enhance.setSuperclass(target.getClass());

                        //2.3设置回调类型,也就是我们需要设置代理对象返回的类型
                        //这里的参数是Callback类型的,需要我们的一个类实现Callback后多态调用到这里,而本类实现了Callback的子接口,并重写了方法,所以可以直接调用this
                        //enhance.setCallback(this);               

                        //2.4调用enhance中的方法增强函数(需要)
                        //return enhance.create();

                return enhance.create(target.getClass(), this);
        }

        /**
         * 3.实现CallBack子接口MethodInterceptor,重写方法
         *
         */
        @Override
        public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
                System.err.println("CGLIB代理加强");
                return arg1.invoke(target, arg2);
                //return arg3.invoke(arg0, arg2);        这是通过方法对应MethodProxy对象去执行,跟上面的其实一样
        }
2.设计模式中,你了解过多少?(这里我只记录了两个)饿汉模式
1.加载:在类加载时直接赋值,占用一定内存
2.时间:较快,调用方法直接返回对象
3.线程安全,高效
public class MyRuntime {
//饿汉式设计模式,永远返回一个对象,不管调用多少次,都是一个对象
//私有构造
private MyRuntime(){}
//私有本类对象
private static MyRuntime md = new MyRuntime();
//定义方法得到本类对象
public static MyRuntime getInstance(){
return md;
}
}
懒汉模式
1.加载:在调用方法时创建对象,节省空间
2.时间:较慢,在调用时才创建对象
3.线程存在安全隐患,需要使用同步锁改进,高效
public class MyRuntime2 {
/*
* 懒汉模式
1.加载:在调用方法时创建对象,节省空间
2.时间:较慢,在调用时才创建对象
3.线程存在安全隐患,需要使用同步锁改进,高效
*/
private MyRuntime2 (){}
private static MyRuntime2 mr2 = null;

//在调用方法返回对象时才创建对象
public static MyRuntime2 getInstance(){
//只有第一次调用方法需要创建对象,再往后就可以直接返回对象,所以在外面加上非空判断,提高效率
if (mr2==null) {
//如果直接走这样的程序存在线程安全隐患,所以加上同步锁就不会出现
synchronized (MyRuntime2.class) {
//如果mr2对象为空,就创建对象,否则直接返回
if (mr2 == null)
mr2 = new MyRuntime2();
}
}
return mr2;
}
}
区别:
饿汉模式创建类时直接赋值给私有对象,占用一定内存,但是高效
懒汉模式在调用方法得到对象时才赋值,节省资源但是费时,并且需要加上同步锁来解决他的线程安全隐患。


作者: zybmemeda852    时间: 2017-12-14 09:34
听君一席话 胜读十年书啊
作者: 黑马与你同在    时间: 2017-12-14 10:22
有心啊,把之前老师提到过的面试题总结下来了。学习生活都应该这样,记录对自己有帮助的东西。并形成自己的东西
作者: MrZhu    时间: 2017-12-14 12:15
有心了,挺不错了,刚巧对懒汉和饿汉印象不深。回顾一下
作者: 温洪达    时间: 2017-12-14 13:04
好多已经有点忘了的概念,看完又想起来了66666
作者: chicbrothet    时间: 2017-12-14 13:27
懒汉式是和恶汉式不是单独的设计模式,是单例模式的两种不同实现
作者: 王天宝    时间: 2017-12-14 13:46
懒汉式和饿汉式好久不用,有点忘了,回顾一下,非常好
作者: wuerzhang    时间: 2017-12-14 17:21
总结的很全面,读到了一些没注意到的细节
作者: 13100837608    时间: 2017-12-14 18:36
很棒棒哦
作者: 13100837608    时间: 2017-12-15 08:10
很不错,很清晰




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2