专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java学习 2019最新大唐电信java面试题及答案

2019最新大唐电信java面试题及答案

更新时间:2019-08-15 15:00:03 来源:动力节点 浏览1984次



1、Java如何实现多态,实现的主要方法。


  java是借助方法的重写和重载实现多态。


  重载的特性,方法名相同.返回类型,传入方法的参数不同(包括个数和类型)。


  重写的特性,方法名相同,返回类型,参数均相同,必须发生在子类。



  2、Hashtable\HashMap有什么区别,HashMap实现的算法思想,多个任意长度的值进行hash操作,得出的hash值是否相等?


(1)Hashtable是继承自陈旧的Dictionary类的,HashMap继承自AbstractMap类同时是Java 1.2引进的Map接口的一个实现。


  (2)也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。


  (3)第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。如果有必要,用containKey()方法来区别这两种情况。


  (4)HashMap去掉了Hashtable的contains方法,保留了containsValue和containsKey方法。


  (5)Hashtable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。


1)首先HashMap里面实现一个静态内部类Entry 其重要的属性有 key , value, next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。


2)既然是线性数组,为什么能随机存取?这里HashMap用了一个小算法,大致是这样实现:


  Java代码

  

  A:存储时:


  B:int hash = key.hashCode();--> 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值


  C:int index = hash % Entry[].length;


  D:Entry[index] = value;


  E:取值时:


  F:int hash = key.hashCode();


    G:int index = hash % Entry[].length;


  H: return Entry[index]



  3、说明inputstream和inputstreamreader的区别


  InputStream是字节流


  reader是字符流


  inputstreamreader是将字节流转换成字符流,是上面两者的转换类。



  4、 Java实现多线程的方法有哪些?什么情况需实现线程同步,线程同步的方法有哪几种?


  多线程有两种实现方法。一种是继承Thread类,一种是实现Runnable接口!


  在多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时修改更改它。


  同步有两种方法。一种同步方法,一种同步代码!分别是synchronized,wait与notify



  5、Xml解析方式有哪几种,有什区别?


  Dom解析在内存中创建一个DOM树,该结构通常需要加载整个文档然后才能做工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的,树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改能随机访问文件内容,也可以修改原文件内容。


  SAX解析 SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点线性解析,不能随机访问,也无法修改原文件。


  JDOM解析 JDOM的目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快.JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用。


  DOM4j解析 DOM4J使用接口和抽象基本类方法。DOM4J大量使用了API中的Collections类,但是在许多情况下,它还提供一些替代方法以允许更好的性能或更直接的编码方法。直接好处是,虽然DOM4J付出了更复杂的API的代价,但是它提供了比JDOM大得多的灵活性。



  6、使用过的触发器有哪几种?有什么区别?


  触发器是一种特殊类型的存储过程,主要是通过事件进行触发而被执行的。


  SQL Server 2000 支持两种类型的触发器:AFTER 触发器和INSTEAD OF 触发器。其中AFTER 触发器即为SQL Server 2000 版本以前所介绍的触发器。该类型触发器要求只有执行某一操作(INSERT UPDATE DELETE)之后,触发器才被触发,且只能在表上定义。可以为针对表的同一操作定义多个触发器。对于AFTER 触发器,可以定义哪一个触发器被最先触发,哪一个被最后触发,通常使用系统过程sp_settriggerorder来完成此任务。


  INSTEAD OF 触发器表示并不执行其所定义的操作(INSERT、 UPDATE、 DELETE),而仅是执行触发器本身。既可在表上定义INSTEAD OF 触发器,也可以在视图上定义INSTEAD OF 触发器,但对同一操作只能定义一个INSTEAD OF 触发器。



  7、Struts和struts2.0有什么区别,使用时需要注意什么?


  /**Action类


  Struts1要求Action类继承一个抽象类,Struts1使用抽象类编程而不是接口


  Struts2可以实现Action接口也可以不实现,Struts2提供一个ActionSuport基类去实现常用接口。Action接口不是必须的,任何有execute的标识的POJO都有可能成为struts2的Action的对象


  /**线程模式


  Struts1的Action是单例模式并且是线程安全的,仅有Action一个实例来处理所有请求。单策略模式限制了Struts1 Action能做的事。比且在开发时要注意Action资源必须是线程安全比且是同步的。


  Struts2的Action对象为每个请求产生一个实例,因此没有线程安全问题。


  /**Servlet依赖


  Struts1 Action依赖与Servlet API,因为当一个Action被调用时HttpServletRequest和HttpServletResponse被传递给execute方法。


  Struts2 Action不依赖与容器,允许Action脱离容器被单独测试。如果需要,struts2依然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问

HttpServletRequest和HttpServletResponse的必要性。


  /**可测性:


  测试Struts1 Action的一个主要问题是execute方法暴漏了Servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)


  struts2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。


  /**捕获输入:


  struts1使用ActionForm对象捕获输入。所有ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的基类不或输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有沉余的JavaBean)。


  Struts2直接使用Acrtion属性作为输入属性,消除了对第二个输入对象的请求。输入属性可能是有自己(子)属性的Rich对象类型。Action属性能过通过web页面上的Taglibs访问。

struts2也支持ActionForm模式。Richard对象类型,包括业务对象,能够用作输入/输出对象。这种ModelDriven特性简化了Taglib对POJO输入对象的引用


  /**表达式语言


  Struts1整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很脆弱。


  Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--“object graph Notation Language”(OGNL)


  /**绑定值到页面(view)


  Struts1使用标准JSP机制吧对象绑定到页面中来访问。


  struts2使用ValueStack技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重同页面(view)


  /**类型转换


  Struts1 ActionForm属性通常都是String类型。struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的


  struts2 使用OGNL进行类型转换,提供基本和常用对象的转换器。


  /**效验


  Struts1支持在ActionForm的validate方法中手动效验,或者通过Commons Validator的扩展来效验。同一个类可以有不同的效验内容,但不能效验子对象。


  Struts2支持通过validate方法和XWork效验框架进行效验。XWork效验框架使用为属性类类型定义的效验和内容效验,来支持Chain效验子属性。


  /**Action执行的控制


  Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。


  struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不能的生命周期。堆栈能够根据需要和不同的Action一起使用。


  10. 使用Java定义一个单链表结构,编程实现对定义的单链表结构的反转。


  /**


  * @author luochengcheng


  * 定义一个单链表


  */


  class Node {


  //变量


  privateint record;


  //指向下一个对象


  private Node nextNode;


  public Node(int record) {


  super();


  this.record = record;


  }


  publicintgetRecord() {


  return record;


  }


  public void setRecord(int record) {



  this.record = record;


  }


  public Node getNextNode() {


  returnnextNode;


  }


  public void setNextNode(Node nextNode) {


  this.nextNode = nextNode;


  }


  }


  /**


  * @author luochengcheng


  * 两种方式实现单链表的反转(递归、普通)


  * 新手强烈建议旁边拿着纸和笔跟着代码画图(便于理解)


  */


  public class ReverseSingleList {


  /**


  * 递归,在反转当前节点之前先反转后续节点


  */


  public static Node reverse(Node head) {


  if (null == head || null == head.getNextNode()) {


  return head;


  }


  Node reversedHead = reverse(head.getNextNode());


  head.getNextNode().setNextNode(head);


  head.setNextNode(null);


  returnreversedHead;


  }


  /**


  * 遍历,将当前节点的下一个节点缓存后更改当前节点指针


  *


  */


  public static Node reverse2(Node head) {


  if (null == head) {


  return head;


  }


  Node pre = head;


  Node cur = head.getNextNode();


  Node next;


  while (null != cur) {


  next = cur.getNextNode();


  cur.setNextNode(pre);


  pre = cur;


  cur = next;


  }


  //将原链表的头节点的下一个节点置为null,再将反转后的头节点赋给head


  head.setNextNode(null);


  head = pre;


  return head;


  }


  public static void main(String[] args) {


  Node head = new Node(0);


  Node tmp = null;


  Node cur = null;


  // 构造一个长度为10的链表,保存头节点对象head


  for (int i = 1; i < 10; i++) {


  tmp = new Node(i);


  if (1 == i) {


  head.setNextNode(tmp);


  } else {


  cur.setNextNode(tmp);


  }


  cur = tmp;


  }


  //打印反转前的链表


  Node h = head;


  while (null != h) {


  System.out.print(h.getRecord() + " ");


  h = h.getNextNode();


  }


  //调用反转方法


  head = reverse2(head);


  System.out.println("\n**************************");


  //打印反转后的结果


  while (null != head) {


  System.out.print(head.getRecord() + " ");


  head = head.getNextNode();


  }


  }


  }


  运行:


  C:\ex>java ReverseSingleList


  0 1 2 3 4 5 6 7 8 9


  **************************


  9 8 7 6 5 4 3 2 1 0



提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>