java基础知识查漏 二

来源:互联网 发布:网络浙江卫视在线直播 编辑:程序博客网 时间:2024/05/18 03:38
一.java基本数据类型所占的内存大小
在Java中一共有8种基本数据类型,其中有4种整型,2种浮点类型,1种用于表示Unicode编码的字符
单元的字符类型和1种用于表示真值的boolean类型。(一个字节等于8个bit)
1.整型
类型              存储需求     bit数    取值范围                备注
int                  4字节          4*8 
short             2字节          2*8    -32768~32767
long              8字节          8*8
byte              1字节           1*8    -128~127
2.浮点型
类型              存储需求     bit数    取值范围      备注
float              4字节           4*8                             float类型的数值有一个后缀F(例 如:3.14F)
double          8字节          8*8                             没有后缀F的浮点数值(如3.14)默认为double类型
3.char类型
类型              存储需求     bit数     取值范围      备注
char              2字节           2*8
4.boolean类型
类型              存储需求    bit数    取值范围      备注
boolean        1字节          1*8      false、true
补充:Java有一个能够表示任意精度的算书包,通常称为“大数值”(big number)。虽然被称为大
数值,但它并不是一种Java类型,而是一个Java对象。
如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中的两个很有用的类:
BigIntegerBigDecimal(Android SDK中也包含了java.math包以及这两个类)这两个类可以处理包含
任意长度数字序列的数值。BigInteger类实现了任意精度的整数运算,BigDecimal实现了任意精度

的浮点数运算。


二、关于汉字在java中存储所占的字节大小(待调查)

java中的char类型是使用UTF16来编码的,也就是说用16位(也就是两字节)来表示一个char,一个汉字需要两字节来存储,所以,一个char刚好可以存下一个汉字。Java一律采用Unicode编码方式,每个字符无论中文还是英文字符都占用2个字节。实际情况下:一个英文字母(不分大小写)占两个字节的空间,但其中一个字节未被使用。一个中文汉字占两个字节的空间。英文标点占两个字节,中文标点占两个字节.用char来存一个英文字母时,有一半的存储空间浪费了,两个字节只利用了一个字节的空间。注意:不同的编码格式占字节数是不同的。UTF-8编码下一个中文所占字节也是不确定的,可能是2个、3个、4个字节。

字符串“学java”在java默认编码下所占字节数为10,每个字符占两个字节。不过,其中“java”占用的8个字节中有4个字节为空。

实现国际化应用常用的手段是利用ResourceBundle类。ResourceBundle能够依据Local的不同,选择性的读取与Local对应后缀的properties文件,以达到国际化的目的。

三、抽象类和接口

抽象类:
用abstract修饰,抽象类中可以没有抽象方法,但有抽象方法的类一定是抽象类,且抽象方法定义时不能有方法体;抽象类不可以实例化只能通过继承在子类中实现其所有的抽象方法;抽象类如果不被继承就没有任何意义;抽象类为子类定义了一个公共类型,封装了子类中的重复内容。
接口:

用Interface关键字定义接口;是特殊的抽象类,因为类中只包含抽象方法;接口中不能定义成员变量可以定义常量;接口是其通过其他类使用implements关键字定义实现类,一个类一旦实现接口就必须实现其中的所有抽象方法;一个类可以实现多个接口,接口名之间用逗号隔开即可;一个接口可以通过extends关键字继承另一个接口,与此同时继承了父类中的所有方法。

四、java.lang包中不能被继承的类
public final class Character
public static final class Character.UnicodeBlock
public final class Class<T>
public final class Compile


public final class Byte
public final class Double
public final class Float
public final class Integer
public final class Short
public final class Long
public final class Math


public final class String
public final class StrictMath
public final class StringBuffer
public final class StringBuilder
public final class ProcessBuilder


public final class RuntimePermission
public final class StackTraceElement


public final class System
public final class Void

五、静态块和构造块
普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”。
构造块:直接在类中用{}定义的而不是出现在类的方法中,且没有加static关键字的代码块称为构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。
静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法(即main方法)执行。如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。
注意:1、静态代码块不能存在于任何方法体内。2、静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。
执行顺序:(优先级从高到低。)静态代码块>main方法>构造代码块>构造方法。
其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。

class Code{    {      System.out.println("Code的构造块");    }        static{        System.out.println("Code的静态代码块");        }            public Code(){        System.out.println("Code的构造方法");        }    }        public class CodeBlock03{     {      System.out.println("CodeBlock03的构造块");         }          static{        System.out.println("CodeBlock03的静态代码块");        }                public CodeBlock03(){             System.out.println("CodeBlock03的构造方法");            }              public static void main(String[] args){            System.out.println("CodeBlock03的主方法");            new Code();            new Code();            new CodeBlock03();            new CodeBlock03();          }    }/*CodeBlock03的静态代码块CodeBlock03的主方法Code的静态代码块Code的构造块Code的构造方法Code的构造块Code的构造方法CodeBlock03的构造块CodeBlock03的构造方法CodeBlock03的构造块CodeBlock03的构造方法*/


public class B{    public static B t1 = new B();    public static B t2 = new B();    {        System.out.println("构造块");    }    static    {        System.out.println("静态块");    }    public static void main(String[] args)    {        B t = new B();    }}
上述代码运行结果:

构造块  //首先执行public static B t1 = new B();这个静态代码块,new调用了构造块

构造块 //再执行public static B t2 = new B();这个静态代码块,new调用了构造块

静态块 //然后执行static{System.out.println("静态");}这个静态代码块

构造块//最后执行main方法,main方法中的B t = new B();语句执行时,首先执行构造代码块,再执行对应的构造函数。


六、==和equal()

在Java中游8种基本数据类型:
浮点型:float(4 byte), double(8 byte)
整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
字符型: char(2 byte)
布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值"true"和"false")
对于这8种基本数据类型的变量,变量直接存储的是“值”,因此在用关系操作符==来进行比较时,比较的就是 “值” 本身。
而对于非基本数据类型的变量,即引用类型的变量。引用类型的变量存储的并不是 “值”本身,而是于其关联的对象在内存中的地址。
对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;如果作用于引用类型的变量,则比较的是所指向的对象的地址是否相同。
对于equals方法,注意:equals方法不能作用于基本数据类型的变量。如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;String类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

七、java的拆箱和装箱

什么是自动装箱拆箱

基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。

一般我们要创建一个类的对象实例的时候,我们会这样:

Class a= new Class(parameter);

当我们创建一个Integer对象时,却可以这样:

Integeri = 100; (注意:不是 int i = 100; )

实际上,执行上面那句代码的时候,系统为我们执行了:Integer i = Integer.valueOf(100);

此即基本数据类型的自动装箱功能。

 

基本数据类型与对象的差别

基本数据类型不是对象,也就是使用int、double、boolean等定义的变量、常量。

基本数据类型没有可调用的方法。

eg:  int t = 1;     t.  后面是没有方法

Integer t =1; t.  后面就有很多方法可让你调用了。

 

什么时候自动装箱

例如:Integer i = 100;

相当于编译器自动为您作以下的语法编译:Integer i = Integer.valueOf(100);

 

什么时候自动拆箱

自动拆箱(unboxing),也就是将对象中的基本数据从对象中自动取出。如下可实现自动拆箱:

Integer i = 10; //装箱

int t = i; //拆箱,实际上执行了 int t =i.intValue();

在进行运算时,也可以进行拆箱。

Integer i = 10;

System.out.println(i++);

 

Integer的自动装箱

在-128~127 之外的数

Integer i1 =200;  

Integer i2 =200;          

System.out.println("i1==i2:"+(i1==i2));       

输出的结果是:

i1==i2: false

 

在-128~127 之内的数

Integer i3 =100; 

Integer i4 =100;  

System.out.println("i3==i4:"+(i3==i4));

输出的结果是: 

i3==i4: true

 

 

 

java中Integer.valueOf的源码

public static Integer valueOf(int i) {

   if(i >= -128 && i <= IntegerCache.high)  // 没有设置的话,IngegerCache.high默认是127

       return IntegerCache.cache[i + 128];

   else

       return new Integer(i);

}

对于–128到127(默认是127)之间的值,Integer.valueOf(int i) 返回的是缓存的Integer对象(并不是新建对象)

所以范例中,i3 与 i4实际上是指向同一个对象。

而其他值,执行Integer.valueOf(int i) 返回的是一个新建的 Integer对象,所以范例中,i1与i2 指向的是不同的对象。

当然,当不使用自动装箱功能的时候,情况与普通类对象一样,请看下例:

Integer i3 =new Integer(100);

Integer i4 =new Integer(100);

System.out.println("i3==i4:"+(i3==i4));//显示false

 

String 的拆箱装箱

 

先看个例子:

String str1 ="abc";

String str2 ="abc";

System.out.println(str2==str1); //输出为 true

System.out.println(str2.equals(str1)); //输出为 true

 

String str3 =new String("abc");

String str4 =new String("abc");

System.out.println(str3==str4); //输出为 false

System.out.println(str3.equals(str4)); //输出为 true

str3与str4也是各自new了个对象,而str1与str2却是引用了同一个对象。


Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);

i01==i02//true(先拆箱,再比较。所以i02==i03,i02==i04都是true)

i01=i03//true(59在-128-127之间,所以返回的是缓存区中的同一个Integer对象)

i04是新建的对象,所以i04==i01,i04==i03都是false


八、jsp的对象和域

Jsp九大内置对象和四种作用域

1.request

 request对象是javax.servlet.httpServletRequest类型的对象。该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。通俗来讲就是客户端的请求信息被封装在Request对象中,并传给服务器。

2.response

 response代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。但在JSP页面中很少直接用到。

3.session

  从客户端到服务器的一次会话,从一个客户打开浏览器并连接到服务器开始,直到客户端与服务器断开连接为止。

4.application

 application服务器启动后就产生application对象,直到服务器结束。实现了用户间数据的共享,可存放全局变量。与session不同的是,所有客户的application对象都是同一个,在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。它是ServletContext类的实例。

5.out

   用于在WEB浏览器内输出信息,并且管理应用服务器上的输出缓冲区。

6.page

   代表JSP本身,只有在JSP页面内才是合法的。类似于Java编程中的this指针。

7.config

   主要作用是取的服务器的配置信息。通过 pageContext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过 config对象传递给这个 Servlet。开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。

8.exception

   Java.lang.Throwable的实例。当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。

9.pageContext

   pageContext对象的作用是获取任何范围的参数,通过它可以获取JSP页面的out、request、response、session、application等对象。pageContext对象的创建和初始化都是由容器来完成,在JSP页面中可以直接使用 pageContext对象。

四种作用域:

 page-> 页面级别,显然只有在一个页面内可用。

 request -> 请求级别 服务器跳转,一次请求之后消失。

 session -> 会话级别 客户端跳转(服务器跳转),与浏览器有关,ie是在重新打开ie时才会不同。

 application = 应用级别,当重启服务器时才会消失

九、java I/O流的层次关系



十、java集合类的特点与区别

java集合类层次关系:

Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap

1.有序/无序和重复元素

 类型

有序否

允许元素重复否

能否存NULL

List

Set

AbstractSet

最多有一个null元素

HashSet

TreeSet

是(用二叉树排序)

Map

AbstractMap

使用key-value来映射和存储数据,

Key必须惟一,value可以重复

 

 允许null,即null value

null key

HashMap

TreeMap

是(用二叉树排序)

2.hashtable与hashmap区别

① HashMap可以存储null键值对,Hashtable不能存储null键值对;
② HashMap是非synchronized,而Hashtable是synchronized。sychronized意味着在一次仅有一个线程能够更改Hashtable。就是说任何线程要更新Hashtable时要首先获得同步锁,其它线程要等到同步锁被放之后才能再次获得同步锁更新Hashtable。也就是说,Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果不需要同步只需要单一线程,那么使用HashMap性能要好过Hashtable。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。所以如果需要完全安全的线程,需要使用Hashtable或者ConcurrentHashMap。

3.List、vector、set、map的区别与联系

Vector : 基于Array的List,其实就是封装了Array所不具备的一些功能方便我们使用,它不可能走出Array的限制。性能也就不可能超越Array。所以,在可能的情况下,我们要多运用Array。另外很重要的一点就是Vector“sychronized”的,这个也是Vector和ArrayList的唯一的区别。
ArrayList:同Vector一样是一个基于Array上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector优越一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。
LinkedList:LinkedList不同于前面两种List,它不是基于Array的,所以不受Array性能的限制。它每一个节点(Node)都包含两方面的内容:1.节点本身的数据(data);2.下一个节点的信息(nextNode)。所以当对LinkedList做添加,删除动作的时候就不用像基于Array的List一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了。这就是LinkedList的优势。
总结:基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操作。


set:虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在HashMap的基础上来实现的,这个就是Set和List的根本区别。

HashSet:HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。Set中不能像在List中一样有重复的项的根本原因,因为HashMap的key是不能有重复的。

LinkedHashSet:HashSet的一个子类,一个链表。
TreeSet:SortedSet的子类,它不同于HashSet的根本就是TreeSet是有序的。它是通过SortedMap来实现的。


4、如何选择?
(1)容器类和Array的区别、择取
* 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。
* 一旦将对象置入容器内,便损失了该对象的型别信息。


(2)
* 在各种Lists中,最好的做法是以ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList();
Vector总是比ArrayList慢,所以要尽量避免使用。
* 在各种Sets中,HashSet通常优于HashTree(插入、查找)。只有当需要产生一个经过排序的序列,才用TreeSet。
HashTree存在的唯一理由:能够维护其内元素的排序状态。 
* 在各种Maps中
HashMap用于快速查找。
* 当元素个数固定,用Array,因为Array效率是最高的。

结论:最常用的是ArrayList,HashSet,HashMap,Array。


5、注意

Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。

List,可以通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...。(add/get)

集合中线程安全的类有:vector,stack,hashtable,enumeration,除此之外均是非线程安全的类与接口。

0 0