java面试(基础篇)

来源:互联网 发布:密山市知一派出所 编辑:程序博客网 时间:2024/06/06 20:49

1、JDK和JRE的区别以及跨平台的原理

    JRE:java的原型环境,包括java虚拟机和java程序所需的核心类库,JVM+类库

    JDK:java的开发工具包,包含java的开发工具,编译工具、打包工具等

        JDK=JRE+Java的开发工具

    跨平台的原理:实现跨平台需要依赖jva的虚拟机jVM,不同平台使用不同的java虚拟机,实现一次编译处处运行

2、java的关键字和标识符及其特点

    java关键字:被java语言赋予特定含义的单词

    特点:组成关键字的字母全部小写,常见的代码编辑器对关键会有特殊的颜色标记

 

    标识符:给类、方法、变量等起名字

    特点:由字符、下划线、美元符$组成,不能以数字开头、不能是java的关键字

3、java的数据类型和分类

        分类:

            基本数据类型:四类八种

            引用数据类型:类、接口、数组

4、java的运算符种类

4.1、算术运算符

        对常量和变量进行操作的运算符

        字符参与运算:其实就是该字符对应的数值操作

        字符串和其它数据类型的数组做拼接,结果是字符串类型

4.2、赋值运算符

4.3、关系运算符

        关系运算符的结果都是boolean性,要么是true要么是false

4.4、逻辑运算符

4.5、三元运算符

 

5、&&和&的区别以及|和||的区别:

&&和&的区别

        &&和&都是逻辑与运算,都是要求运算符两侧的表达式为true,结果才为true。&& 具有短路效果,当左侧的表达式结果为false时,右侧将不再执行。&是无论左侧是     否为false,将继续执行下去。&还可以用于按位与

   

|和||的区别

        最终的结果是一样的,||具有短路效果,左侧为true,右边将不再执行,|是无论 左边是false还是true,右边都会执行

6、键盘录入的对象创建

    Scannersc = new Scanner(System.in);

    再调用sc.nextInt()的等函数

7、数组

    数组是存储同一种数据类型多个元素的容器

两种初始化方式:

        初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值

        动态初始化:初始化时只指定数组长度、并有系统为数组分配初始化值

        静态初始化:初始化指定每个数组元素的初始化值,有系统决定数组长度

8、JVM的内存划分

    栈:存储局部变量

    堆:存储new出来的东西

    方法区:

    本地方法区:与系统相关

    寄存器:给CPU使用

9、方法重载和方法重写

    方法重载:在同一个类中,允许多个同名方法,只要他们的参数个数或者参数类型不同即可,方法名相同,参数类型不同,分为参数个数不同,参数类型不同,与返回值无关

    方法重写:存在于子父类之间,子类的方法的权限修饰符权限大于或等于父类的,方法名和参数类型完全相同,与返回值有关

10、方法中的参数传递

    形参为基本数据类型:形参的改变不影响实际参数

    形参为引用数据类型:形参的改变会影响实际参数

 

11、面向对象的特征

1、封装

        将客观事物封装成抽象的类,一个类就是一个封装了数据和操作的这些数据的代码        的逻辑实体

2、继承

        可以让其他类型的得对象获得另一个类型的对象的属性的方法。它可以使用          现有类的所有功能,并在无需重写原来类的情况下对这些功能进行扩展

3、多态

        父类或父接口引用指向的子类对象

 

12、面向对象的特点

    更符合我们的思考方式,将事情将给其他人去做,将复杂事情简单化,我们从执行者变    成了指挥者角色

 

13、类与对象的关系

    类:是一组相关属性和行为的集合

    对象:是该类事物的具体体现

 

14、String、StringBuffer、StringBuilder

    String:字符串常量,字符串长度不变,是被声明程final的,一次赋值不可改变

    StringBuffer:字符串变量,线程安全,如果需要频繁的对字符串内容进行修改,处于效率考虑最好使用StringBuffer。StringBuffer,在任意时间点上都包含特定的字符序列,但通过方法调用改变长度和内容

    StringBuilder:字符串变量,非线程安全。StringBuilder对象被当做一个包含字符序列的变长数组,是在JDK1.5后新增的,可用于字符串缓冲区被单线程使用时使用

 

15、String对象的两种创建方式

    通过构造方法创建字符串对象是在堆内存

    直接赋值方式创建对象是方法区的常量池

 

16、String是基本的数据类型

    String类是final类型,因此这个类不能被继承,不能修改。为了提高效率节省空间,使用StringBuilder类

 

17、GC是什么?为什么要用GC

    GC是垃圾回收的意思,内存处理是编程人员容易出现的问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,java提供的GC功能可以自动检测对象是否超过作用域从而达到自动回收的目的,java语言没有提供释放已分配内存的显示操作方法。

 

18、java中有几种类型的流

    字节输入流:InputStream 字节输出流:OutputStream

    字符输入流:Reader      字符输出流:Writer

 

19、什么是java序列化,如何实现java序列化

    java对象的序列化是指将一个java对象写入IO流中,于此对应的是,对象的反序列化则是从IO流中恢复的Java对象。如果要让某个对象支持反序列化机制,必须让它的类是可序列化,则需要实现Serializable接口或者Externalizable接口

 

20、对象在序列化时不想给一个字段的数据保存到硬盘上

    使用transient关键字

 

21、IO中的适配器模式

    适配器模式:讲一个累的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作在java IO中。

    BufferedReaderbr = new BufferedReader(new InputStreamReader(is2,"utf8"));

        (将字节流接口,转换成字符流接口)

    br.readLine();

    因为要逐行解析字符串, 我们需要使用字符流,对文件内容进行处理, 所以使用Reader输入流下面的BufferedReader,BufferedReader并不能直接处理文件,它需要传入一个Reader类型的参数,Reader下面能处理文件的类:InputStreamReader,以及其子类FileReader,这2个类都需要一个InputStream来读取文件中的内容并转换, 这2个类其实就是适配器, 可以把字节流转换成字符流, 然后使用Reader来解析其中的内容

 

22、IO中的装饰模式

    装饰模式就是对一个类进行装饰,增强其方法行为,在装饰模式中,作为原来的这个类的使用者应该感受不到装饰前和装饰后的不同。装饰模式就是对原有功能的扩展。

 

22、适配器模式和装饰模式的总结

    适配器模式主要是将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。装饰模式则是不是改变被装饰对象的接口,而是保持原来的接口,但是增强了元有对象的功能,或改变原有对象的方法而提高性能

 

23、同步和异步、阻塞和非阻塞

    同步:当一个同步调用发出后,调用者要一直等待返回消息通知后,才能进行后续执行

    异步:当一个异步过程调用发出后,调用者不能立刻得到返回消息。在调用结束后,通过消息回调来通知调用者是否成功

    阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务,函数只有在得到结果后才会返回

    非阻塞:非阻塞和阻塞的概念相对应,指再不能立刻得到借过钱,该函数不会阻塞当前线程,而会立刻返回

 

    同步和异步的重点在于消息通知的方式,也就是调用结果通知的方式

    阻塞和非阻塞的重点是当前线程等待消息返回的行为

    分类:同步阻塞、同步非阻塞、异步阻塞、异步非阻塞

 

24、进程和线程的区别

    进程是正在进行中的程序。线程其实就是进程中一个程序执行控制单元,一条执行路径。进程负责的是应用程序的空间的标示。

    一个进程至少有一个线程在运行,当一个进程中出现多个线程时,这个应用程序就是多线程应用程序,每个线程在栈区都有自己的执行空间,自己的方法区、自己的变量。

 

25、线程的运行

    start方法,作用1、启动了线程,2)、让jvm调用了run方法

 

26、创建线程的方式

    1)、继承Thread,由子类重写run方法,由run方法体来完后曾线程需要做的事

    2)、实现了Runnable接口,由run方法体来完后曾线程需要做的事

    3)、通过Callable和FutrueTask创建线程。创建Callable的实现类,实现call()方法,该call()方法作为线程执行体,并有返回值

    创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

 

27、多线程安全问题

    当一个线程执行多条语句时,并运算同一个数据时,在执行过程中,其他线程参与进来,并操作这个数据,导致了错误数据的产生

    涉及到两个因素

        1、多个线程在操作共享数据

        2、有多条数据对共享数据进行运算

    解决方案:

        只要将操作共享数据的语句在某一个时段让一个线程执行完,在执行过程中,其他线程不能进来执行就可以解决--------使用同步代码块

   

28、同步的好处与弊端

    好处是解决了线程安全问题,弊端是相对降低性能,因为判断锁需要资源,产生了死锁

    前提:必须有两个及以上的线程才需要同步,多个线程必须保证是同一个锁

 

29、同步代码块和同步函数的区别

    同步代码块使用的锁可以是任意对象

    同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象

    在一个类中只有一个同步,可以使用同步函数。如果有多同步,必须使用同步代码块,来确定不同的锁。同步代码块相对灵活一些

 

30、请写一个延迟加载的单例模式?写懒汉式;当出现多线程访问时怎么解决?加同步,解决安全问题;效率高吗?不高;怎样解决?通过双重判断的形式解决。

//懒汉式:延迟加载方式。

当多线程访问懒汉式时,因为懒汉式的方法内对共性数据进行多条语句的操作。所以容易出现线程安全问题。为了解决,加入同步机制,解决安全问题。但是却带来了效率降低。

为了效率问题,通过双重判断的形式解决。

class Single{

    privatestatic Single s = null;

    privateSingle(){}

    publicstatic Single getInstance(){ //锁是谁?字节码文件对象;

        if(s== null){

            synchronized(Single.class){

                if(s== null)

                    s= new Single();

            }

        }

        returns;

    }

}

   

31、等待唤醒机制

    wait:将同步中的线程处于冻结状态。释放了执行权,释放了资格,同时将线程对象存在线程池中

    notify:唤醒线程池中的某一个等待线程

    notifyAlll:唤醒的是线程池中的所有线程

 

32、sleep和wait的区别

    wait:可以指定时间也可以不指定时间,不指定时间,只能由对应的notify或者notifyall来唤醒

    sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)

    wait:线程会释放执行权,而且线程会释放锁

    sleep:线程会释放执行权,但不释放锁

 

33、线程死锁的出现和解决办法

    当线程任务出现了多个同步(多个锁)时,如果同步嵌套了其他的同步,这时容易引发一种现象:线程出现无限等待,都在等待对方的执行结束

    解决方案:线程按照一定的顺序加锁,按照同一顺序访问对象,避免事务中用户的交互,保持事务处于一个批处理,死锁检测

 

34、lock和synchronize的区别

    lock不是java内置的,synchronize是java的关键字,lock是一个类,通过这个类可以实现同步访问

    Lock和Synchronize的最大不同:采用Synchronize不需要用户去手动加锁,当Synchronize方法或者代码块执行完成后,系统会自动让线程释放对锁的占用,而lock则必须要用户手动释放锁,如果没有自动释放锁,会出现死锁的现象

 

35、启动一个线程是run()还是start()?它们的区别?

    启动一个线程是start()

    区别:

        start: 启动线程,并调用线程中的run()方法

        run  : 执行该线程对象要执行的任务

 

36、单例设计模式

    两种方式

A:饿汉式:当类加载时就创建对象

        class Student{

            privateStudent(){}

   

            private static final Student s = newStudent();

       

            publicstatic Student getInstance(){

                returns;

            }

        }

B:懒汉式 当使用的时候,才去创建对象

        classStudent{

            privateStudent(){}

   

            privatestatic final Student s = null;

       

            publicstatic Student getInstance(){

                if(s==null){

                    //线程1进来了,线程2就进来了

                    s= new Student();

                }

                returns;

            }

        }

饿汉式和懒汉式的区别

        饿汉式是类一加载就创建好对象,

        懒汉式是类加载进内存,对象还没有存在,只有调用getInstance()方法才创建对象

       

        懒汉式是延迟加载,如果多个线程同时操作懒汉式就可以出现线程安全问题,

        开发中常使用饿汉式,因为饿汉式安全。

 

37、Java中创建(实例化)对象的五种方式

    1、用new语句创建对象,这是最常见的创建对象的方法。

    2、通过工厂方法返回对象,如:String str = String.valueOf(23);

    3、运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()     实例方法。如:Object obj =Class.forName("java.lang.Object").newInstance();

    4、调用对象的clone()方法。

    5、通过I/O流(包括反序列化),如运用反序列化手段,调用java.io.ObjectInputStream     对象的 readObject()方法。

 

38、异常

    程序运行过程中的不正常现象叫做异常

    异常的根类是Throwable

        |--Error:重大问题,处理不了,例如JVM内存溢出  

        |--Exception:一般性错误,需要我们编写代码进行处理

           

39、异常的分类:

    编译时异常

            在编译时,如果没有处理,编译失败

    运行时异常

            在编译时,不需要处理,编译器不检查

            该异常的发生,减一不处理,让程序停止,需要对代码进行修正

 

40、java中三种常见内存溢出错误的处理方法

    jvm管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域)、Heapspace(堆区域)、Java Stacks(Java栈)。

第一种OutOfMemoryError: PermGen space

        原因是:程序中使用了大量的jar或class,使java虚拟机装载类的空间不够   

        解决方案:

            1、增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中         XX:PermSize是初始永久保存区域大 小,XX:MaxPermSize是最大永久保存区域大小。

            2、清理应用程序中web-inf/lib下的jar,如果tomcat部署了多个应用,很多           应用都使用了相同的jar,可以将共同的jar移到tomcat共同的lib下,减少类的重     复加载。

第二种OutOfMemoryError:  Java heap space

        原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内     存空间已经用满了,与Heapspace有关

    解决方案:

        1、检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改 程序和算法。

        2、增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。

第三种OutOfMemoryError:unable to create new native thread

        因为JVM已经被系统分配了大量的内存,并且它至少要占用可用内存的一半

        要想创建更多的线程,你必须减少分配给JVM的最大内存

 

41、final、finally、finalize区别

    final是最终的意思,可以用于修饰类、成员变量、成员方法

        它修饰的类不能被继承,修饰的变量是常量,修饰方法不能被重写

    finally:是一场处理里面的关键字

        它其中的代码永远会被执行,特殊情况:在执行前jvm退出

    finalize是Object类中的一个方法

        它用于垃圾回收器调用方式

42、什么是锁?锁的作用是什么?

    锁就是对象

    锁的作用是保证线程同步,解决线程安全问题。

    持有锁的线程可以在同步中执行,没有锁的线程即使获得cpu执行权,也进不去。

 

43、什么是ThreadLocal类,怎么使用它?

    ThreadLocal类提供了线程局部 (thread-local) 变量。是一个线程级别的局部变量,并非“本地线程”。

    ThreadLocal为每个使用该变量的线程,提供了一个独立的变量副本,每个线程修改副本时不影响其它线程对象的副本

 

    下面是线程局部变量(ThreadLocal variables)的关键点:

        一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。

       ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程。

        当多个线程访问 ThreadLocal 实例时,每个线程维护 ThreadLocal 提供的独立的变量副本。

        常用的使用可在 DAO 模式中见到,当 DAO 类作为一个单例类时,

        数据库链接(connection)被每一个线程独立的维护,互不影响。(基于线程的单例)

 

44、集合和数组的区别

    数组的长度是固定的,而集合长度是可变的

    数组值可以存储对象,还可以存储基本数据类型;而集合只能够只能存储对象

    数组存储的数据类型是固定的,而集合存储的数据类型不固定

 

45、HashSet是如何保证元素唯一性的呢?

    如果两元素的hashCode值不同,则不会调用equals方法

    如果两元素的hashCode值相同,则继续判断equals是否返回true;

    hashCode和equals方法虽然定义在自定义对象类里面,但不是我们手动调用而是往           HashSet集合里面存储元素的时候,集合底层自己调用hashCode和equals它自己      拿对象去判断,自己判断两元素是否是同一个元素。

 

46、Map

    Map:顶层接口,该集合存储的是键值对,而且键是唯一的,Map和Set很像,Set集合底层就   是使用了Map集合。

    Map集合没有迭代器,要取出元素必须先将Map集合转换成Set集合才能遍历元素

       |--->HashTable(JDK1.0):

        底层是哈希表数据结构;

        不可以使用null键和null值;

        用作键的对象必须实现hashCode和equals方法来保证键的唯一性

        线程同步,效率低

       |--->HashMap(JDK1.2):

        底层是哈希表数据结构;

        允许使用null键和null值;

        线程不同步,效率高;

        保证元素唯一性的:

             原理:先判断元素的hashCode值是否相同,再判断两元素的equals方法是     否为true

         (往HashSet里面存的自定义元素要复写hashCode和equals方法,以保证元素的    唯一性!)

 

47、LisIterator、Comparable、Comparator、Collections和Arrays

    LisIterator:系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表       Comparable:此接口强行对实现它每个类的对象进行整体自然排序。使元素具备比较性

    Comparator:强行对某个对象collection进行整体排序的比较函数,使集合具备比较性

    Collections:此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。

    Arrays:此类包含用来操作数组(比如排序和搜索)的各种静态方法

 

48、Map集合和Collection集合的区别?

    (1)

        Map中一次存储是键值对。

        Collection中一次存储是单个元素。

    (2)

        Map的存储使用的put方法。

        Collection存储使用的是add方法。

    (3)

        Map集合没有迭代器,Map的取出,是将Map转成Set,在使用迭代器取出。

        Collection取出,使用就是迭代器。

    (4)

        如果对象很多,必须使用集合存储。

        如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,

        如果没有映射关系,可以使用Collection存储。

 

49、IO流常用基类方法摘要:

        **字节写入流:OutputStream:

            voidclose() 关闭此输出流并释放与此流有关的所有系统资源。

            voidflush()刷新此输出流并强制写出所有缓冲的输出字节。

            abstract  void write(int b)  将指定的字节写入此输出流。

            voidwrite(byte[] b) 将 b.length 个字节从指定的 byte数组写入此输出流。   

            voidwrite(byte[] b, int off, int len)

                    将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

        **字节读取流:InputStream:

            voidclose() 关闭此输入流并释放与该流关联的所有系统资源。

            intavailable() (特有方法!!)

                返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)                的估计字节数。

            abstract  int read() 从输入流中读取数据的下一个字节。

            intread(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组                  b中。

            intread(byte[] b, int off, int len) 将输入流中最多len个数据字节读入byte数组。

            longskip(long n) 跳过和丢弃此输入流中数据的 n 个字节。

          

        **字符写入流:Writer:

            abstract  void close() 关闭此流,但要先刷新它。

            abstract  void flush() 刷新该流的缓冲。

            voidwrite(int c) 写入单个字符。

            voidwrite(char[] cbuf) 写入字符数组。         

            abstract  void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。

            voidwrite(String str) 写入字符串。

            voidwrite(String str, int off, int len) 写入字符串的某一部分。

        **字符读取流:Reader:

            abstract  void close() 关闭该流并释放与之关联的所有资源。

            intread() 读取单个字符。

            intread(char[] cbuf)  将字符读入数组

            abstract  int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。

            longskip(long n)  跳过字符。

 

50、流的操作流程

    (1)第一步:先明确源和目的

        源:

            文本:用Reader

            字节:用InputStream

        目的:

            文本:用Writer

            字节:用OutputStream

    (2)第二步:明确是不是纯文本

        是:用字符流;

        不是:用字节流

    (3)第三步:明确流体系后,通过设备来明确具体使用哪个流对象

        源设备:

            键盘:System.in

            硬盘:文件流File

            内存:数组流ArrayStream

        目的设备:

            键盘:System.out

            硬盘:文件流File

            内存:数组流ArrayStream

 

51、File类常见需求:

(1)文件名过滤:列出给定目录的所有.java文件

        publicvoid showFileName(File file)

        {

            String[]filenames = file.list(new FilenameFilter()//匿名内部类

            {

                publicboolean accept(File dir,String name)//复写唯一方法

                {

                    returnname.endsWith(".java");//列出所有.java文件

                }

            });

        }

(2)列出指定目录下的所有文件和文件夹(递归)

    **示例1:不带层次递归:

    publicstatic void showDir(File dir)

    {

        File[]files = dir.listFile();

        for(inti = 0;i<files.length;i++)

        {

            if(files[i].isDirectory&&!files[i].isHidden())

                showDir(files[i]);

            else

                sop(files[i]);

        }

    }

    **示例2:带层次递归:

    publicstatic void showDir(File dir,int level)

    {

        sop(getLevel(level)+C);//进来先打印层次和目录

        level++;

        File[]files = dir.listFile();

        for(inti = 0;i<files.length;i++)

        {

            if(files[i].isDirectory&&!files[i].isHidden())

                showDir(files[i]);

            else

                sop(getLevel(level)+files[i]);//是文件就打印层次和目录

        }

    }

    publicstatic String getLevel(int level)

    {

        sop("|--");

        StringBuildersb = new StringBuilder();

        for(inti=0;i<level;i++)

        {

            sb.inset(0."|  ")

        }

        returnsb.toString();

    }

(3)需求:删除带内容的目录:

    publicstatic void removeDir(File dir)

    {

        File[]files = file.listFile();

        for(inti = 0;i<files.length;i++)

        {

            if(files[i].isDirectory&&!files[i].isHidden())

                removeDir(files[i]);//如果是文件夹则继续调用函数

            else//如果是文件则删除。注意删除的时候打印删除的结果,防止误删或者重删的情况

                sop(files[i].toString()+"::"+files[i].delete());

        }

        sop(dir+"::"+dir.delete());

    }

 (4)需求:将制定目录下java文件的绝对路径存储到文本文件中。

       思路:

       **对指定目录进行递归

       **获取递归过程中所有java文件的路径

       **将这些路径存储到集合中

       **将集合中的数据写入文件中

     //对指定目录进行递归并将所以Java文件存储到集合中

    publicstatic void getFileName(File file,ArrayList<File> arraylist){

        File[]files = file.listFiles();

        for(int i = 0; i < files.length; i++) {

            if(files[i].isDirectory()&&!files[i].isHidden()){

                getFileName(files[i],arraylist);

            }else{

                if(files[i].getName().endsWith(".java")){

                    arraylist.add(files[i]);

                }

            }

        }

    }

    //将集合中所有数据存储到新文件中

    publicstatic void saveFileToNewDir(ArrayList<File> arraylist,File newDir){

        BufferedWriterbufw = null;

        try{

            bufw= new BufferedWriter(new FileWriter(newDir));

            for(File file : arraylist) {

                StringfileAbsolutePath = file.getAbsolutePath();

                bufw.write(fileAbsolutePath);

                bufw.newLine();

                bufw.flush();  

            }

        }catch (Exception e) {

            System.out.println("文件写入失败");

        }finally{

            try{

                if(bufw!=null)

                    bufw.close();

            }catch (Exception e2) {

                System.out.println("文件写入流关闭失败");

            }

        }

    }

 

52、Properties

    (1)Properties是HashTable的子类,具备Map集合的特点,里面存储的是键值对

    (2)Properties是IO流合集合相结合的集合容器

    (3)Properties的特点是可以用于存储键值对形式的配置文件

 

53、网络模型:

OSI模型

        应用层、表示层、会话层、传输层、网络层、数据连接层、物理层

TCP/IP模型

        应用层、传输层、网际层、主机至网络层

 

54、UDP和TCP的区别:

UDP

        将数据及源和目的封装成数据包中,不需要建立连接

        每个数据报的大小在限制在64k内

        因无连接,是不可靠协议

        不需要建立连接,速度快

TCP

        建立连接,形成传输数据的通道。

        在连接中进行大数据量传输

        通过三次握手完成连接,是可靠协议

        必须建立连接,效率会稍低

55、XML文档的定义形式?他们之间的本质区别,解析XML文档的方式

    XMl文档定义分为DTD和Schema两种形式,二者都是对XML语法的约束,其本质的区别在于Schema本省就是一个xml文件,可以被XML解析器解析,而且乐意为XML承载的数据定义类型约束比DTD更强大。

    对XML的解析主要有DOM(文档对象模型),SAX和StAX。

    DOM处理大型文件时其性能下降的非常厉害,这个问题是由DOM树结构占用的内存较多造成的,而且DOM解析方式必须在解析文件之前把整个文档装入内存,适合对XML的随机访问(典型的用空间换取时间的策略);SAX是事件驱动型的XML解析方式,它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时

 

56、你在项目中哪些地方用到了XML?

    XML的主要作用有两个方面:数据交换和信息配置。在做数据交换时,XML将数据用标签组装成起来,然后压缩打包加密后通过网络传送给接收者,接收解密与解压缩后再从XML文件中还原相关信息进行处理,XML曾经是异构系统间交换数据的事实标准,但此项功能几乎已经被JSON(JavaScriptObjectNotation)取而代之。

原创粉丝点击