您好,欢迎访问三七文档
2016/7/19OneNoteOnline=87F1B9C0B4E76F16!1539&app=OneNote&authkey=!AFQOmNVYeyu9J4M1/191. 自我介绍 2. 做过的项目 (Java 基础) 3. Java的四个基本特性(抽象、封装、继承,多态),对多态的理解(多态的实现方式)以及在项目中那些地方用到多态 Java的四个基本特性 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供昀简单的编程接口。 多态性是指允许不同子类型的对象对同一消息作出不同的响应。 多态的理解(多态的实现方式) 方法重载(overload)实现的是编译时的多态性(也称为前绑定)。 方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象昀精髓的东西。 要实现多态需要做两件事:1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。 项目中对多态的应用 举一个简单的例子,在物流信息管理系统中,有两种用户:订购客户和卖房客户,两个客户都可以登录系统,他们有相同的方法Login,但登陆之后他们会进入到不同的页面,也就是在登录的时候会有不同的操作,两种客户都继承父类的Login方法,但对于不同的对象,拥有不同的操作。 4. 面向对象和面向过程的区别?用面向过程可以实现面向对象吗?那是不是不能面向对象? 面向对象和面向过程的区别 面向过程就像是一个细心的管家,事无具细的都要考虑到。而面向对象就像是个家用电器,你只需要知道他的功能,不需要知道它的工作原理。 面向过程”是一种是事件为中心的编程思想。就是分析出解决问题所需的步骤,然后用函数把这些步骤实现,并按顺序调用。面向对象是以“对象”为中心的编程思想。 简单的举个例子:汽车发动、汽车到站 这对于“面向过程”来说,是两个事件,汽车启动是一个事件,汽车到站是另一个事件,面向过程编程的过程中我们关心的是事件,而不是汽车本身。针对上述两个事件,形成两个函数,之 后依次调用。 然而这对于面向对象来说,我们关心的是汽车这类对象,两个事件只是这类对象所具有的行为。而且对于这两个行为的顺序没有强制要求。 用面向过程可以实现面向对象吗 那是不是不能面向对象 5. 重载和重写,如何确定调用哪个函数 重载:重载发生在同一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载。 重写:重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。根据不同的子类对象确定调用的那个方法。 6. 面向对象开发的六个基本原则(单一职责、开放封闭、里氏替换、依赖倒置、合成聚合复用、接口隔离),迪米特法则。在项目中用过哪些原则 六个基本原则 单一职责:一个类只做它该做的事情(高内聚)。在面向对象中,如果只让一个类完成它该做的事,而不涉及与它无关的领域就是践行了高内聚的原则,这个类就只有单一职责。 开放封闭:软件实体应当对扩展开放,对修改关闭。要做到开闭有两个要点:①抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;②封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱。 里氏替换:任何时候都可以用子类型替换掉父类型。子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。 依赖倒置:面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代) 合成聚和复用:优先使用聚合或合成关系复用代码。 接口隔离:接口要小而专,绝不能大而全。臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。 迪米特法则 迪米特法则又叫昀少知识原则,一个对象应当对其他对象有尽可能少的了解。 项目中用到的原则 单一职责、开放封闭、合成聚合复用(昀简单的例子就是String类)、接口隔离 7. static和final的区别和用途 Static 修饰变量:静态变量随着类加载时被完成初始化,内存中只有一个,且JVM也只会为它分配一次内存,所有类共享静态变量。 修饰方法:在类加载的时候就存在,不依赖任何实例;static方法必须实现,不能用abstract修饰。 阿里面经 2016年4月23日 14:35 2016/7/19OneNoteOnline=87F1B9C0B4E76F16!1539&app=OneNote&authkey=!AFQOmNVYeyu9J4M2/19修饰代码块:在类加载完之后就会执行代码块中的内容。 父类静态代码块子类静态代码块父类非静态代码块父类构造方法子类非静态代码块子类构造方法 Final 修饰变量: 编译期常量:类加载的过程完成初始化,编译后带入到任何计算式中。只能是基本类型。 运行时常量:基本数据类型或引用数据类型。引用不可变,但引用的对象内容可变。 修饰方法:不能被继承,不能被子类修改。 修饰类:不能被继承。 修饰形参:final形参不可变 8. Hash Map和Hash Table的区别,Hash Map中的key可以是任何对象或数据类型吗?HashTable是线程安全的么? Hash Map和Hash Table的区别 Hashtable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。 Hashtable不允许 null 值(key 和 value 都不可以),HashMap允许 null 值(key和value都可以)。 两者的遍历方式大同小异,Hashtable仅仅比HashMap多一个elements方法。 Hashtable 和 HashMap 都能通过values()方法返回一个 Collection ,然后进行遍历处理。 两者也都可以通过 entrySet() 方法返回一个 Set , 然后进行遍历处理。 HashTable使用Enumeration,HashMap使用Iterator。 哈希值的使用不同,Hashtable直接使用对象的hashCode。而HashMap重新计算hash值,而且用于代替求模。 Hashtable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。 HashTable基于Dictionary类,而HashMap基于AbstractMap类 Hash Map中的key可以是任何对象或数据类型吗 可以为null,但不能是可变对象,如果是可变对象的话,对象中的属性改变,则对象HashCode也进行相应的改变,导致下次无法查找到已存在Map中的数据。 如果可变对象在HashMap中被用作键,那就要小心在改变对象状态的时候,不要改变它的哈希值了。我们只需要保证成员变量的改变能保证该对象的哈希值不变即可。 HashTable是线程安全的么 HashTable是线程安全的,其实现是在对应的方法上添加了synchronized关键字进行修饰,由于在执行此方法的时候需要获得对象锁,则执行起来比较慢。所以现在如果为了保证线程安全的话,使用CurrentHashMap。 9. HashMap和Concurrent HashMap区别, Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全? HashMap和Concurrent HashMap区别? HashMap是非线程安全的,CurrentHashMap是线程安全的。 ConcurrentHashMap将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁。 ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。 Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全? HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 get操作的高效之处在于整个get过程不需要加锁,除非读到的值是空的才会加锁重读。get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。 Put方法首先定位到Segment,然后在Segment里进行插入操作。插入操作需要经历两个步骤,第一步判断是否需要对Segment里的HashEntry数组进行扩容,第二步定位添加元素的位置然后放在HashEntry数组里。 10. 因为别人知道源码怎么实现的,故意构造相同的hash的字符串进行攻击,怎么处理?那jdk7怎么办? 怎么处理构造相同hash的字符串进行攻击? 当客户端提交一个请求并附带参数的时候,web应用服务器会把我们的参数转化成一个HashMap存储,这个HashMap的逻辑结构如下:key1value1; 但是物理存储结构是不同的,key值会被转化成Hashcode,这个hashcode有会被转成数组的下标:0value1; 不同的string就会产生相同hashcode而导致碰撞,碰撞后的物理存储结构可能如下:0value1value2; 1、限制post和get的参数个数,越少越好 2、限制post数据包的大小 3、WAF Jdk7 如何处理hashcode字符串攻击 HashMap会动态的使用一个专门的treemap实现来替换掉它。 11. String、StringBuffer、StringBuilder以及对String
本文标题:阿里java面试
链接地址:https://www.777doc.com/doc-4482781 .html