[转] C#与Java的比较

[转] C#与Java的比较

转自:C#与Java的比较

2015-06-26

目录

一、C#、C++和Java
二、语言规范的比较
  2.1、简单数据类型
  2.2、常量
  2.3、公用类的入口点
  2.4、switch语句
  2.5、foreach语句
  2.6、C#没有>>>移位操作符
  2.7、goto关键词
  2.8、声明数组
  2.9、包
  2.10、默认包
  2.11、面向对象
  2.12、可访问性
  2.13、派生类
  2.14、最终类
  2.15、接口
  2.16、is和as操作符
  2.17、库
  2.18、垃圾收集
  2.19、异常处理
三、Java没有的功能
  3.1、枚举器
  3.2、结构
  3.3、属性
  3.4、以引用方式传递简单数据类型的参数
  3.5、C#保留了指针
  3.6、代理
  3.7、包装和解除包装

C#(C-Sharp)是Microsoft的新编程语言,被誉为“C/C++家族中第一种面向组件的语言”。然而,不管它自己宣称的是什么,许多人认为C#更像是Java的一种克隆,或者是Microsoft用来替代Java的产品。事实是否是这样的呢?

本文的比较结果表明,C#不止是Java的同胞那么简单。如果你是一个Java开发者,想要学习C#或者了解更多有关C#的知识,那么本文就是你必须把最初10分钟投入于其中的所在。

一、C#、C++和Java



返回

C#的语言规范由Microsoft的Anders Hejlsberg与Scott Wiltamuth编写。在当前Microsoft天花乱坠的宣传中,对C#和C++、Java作一番比较总是很有趣的。考虑到当前IT媒体的舆论倾向,如果你早就知道C#更接近Java而不是C++,事情也不值得大惊小怪。

对于刚刚加入这场讨论的读者,下面的表1让你自己作出判断。显然,结论应该是:Java和C#虽然不是孪生子,但C#最主要的特色却更接近Java而不是C++。


表1:比较C#、C++和Java最重要的功能


功能


C#


C++


Java


继承


允许继承单个类,允许实现多个接口


允许从多个类

继承


允许继承单个类,允许实现多个接口


接口实现


通过“interface”关键词


通过抽象类


通过“interface”关键词


内存管理


由运行时环境管理,使用垃圾收集器


需要手工管理


由运行时环境管理,使用垃圾收集器


指针


支持,但只在很少使用的非安全模式下才支持。通常以引用取代指针


支持,一种很常用的功能。


完全不支持。代之以引用。


源代码编译后的形式


.NET中间语言(IL)


可执行代码


字节码


单一的公共基类





异常处理


异常处理


返回错误


异常处理。

二、语言规范的比较



返回

2.1、简单数据类型

简单数据类型(Primitive)在C#中称为值类型,C#预定义的简单数据类型比Java多。例如,C#有unit,即无符号整数。

表2列出了所有C#的预定义数据类型:


表2:C#中的值类型


类型


说明


object


所有类型的最终极的基类


string


字符串类型;字符串是一个Unicode字符的序列


sbyte


8位带符号整数


short


16位带符号整数


int


32位带符号整数


long


64位带符号整数


byte


8位无符号整数


ushort


16位无符号整数


uint


32位无符号整数


ulong


64位无符号整数


float


单精度浮点数类型


double


双精度浮点数类型


bool


布尔类型;bool值或者是true,或者是false


char


字符类型;一个char值即是一个Unicode字符


decimal


有28位有效数字的高精度小数类型

2.2、常量

忘掉Java中的static final修饰符。在C#中,常量可以用const关键词声明。

public const int x = 55;

此外,C#的设计者还增加了readonly关键词。如果编译器编译时未能确定常量值,你可以使用readonly关键词。readonly域只能通过初始化器或类的构造函数设置。

2.3、公用类的入口点

在Java中,公用类的入口点是一个名为main的公用静态方法。main方法的参数是String对象数组,它没有返回值。在C#中,main方法变成了公用静态方法Main(大写的M),Main方法的参数也是一个String对象数组,而且也没有返回值,如下面的原型声明所示:

public static void Main(String[] args)

但是,C#的Main方法不局限于此。如果不向Main方法传递任何参数,你可以使用上述Main方法的一个重载版本,即不带参数列表的版本。也就是说,下面的Main方法也是一个合法的入口点:

public static void Main()

另外,如果你认为有必要的话,Main方法还可以返回一个int。例如,下面代码中的Main方法返回1:

 1 using System;
 2
 3 public class Hello {
 4
 5 public static int Main() {
 6
 7 Console.WriteLine("Done");
 8
 9 return 1;
10
11 }
12
13 }

与此相对,在Java中重载main方法是不合法的。

2.4、switch语句

在Java中,switch语句只能处理整数。但C#中的switch语句不同,它还能够处理字符变量。请考虑下面用switch语句处理字符串变量的C#代码:

 1 using System;
 2
 3 public class Hello {
 4
 5 public static void Main(String[] args) {
 6
 7 switch (args[0]) {
 8
 9 case "老板":
10
11 Console.WriteLine("早上好!我们随时准备为您效劳!");
12
13 break;
14
15 case "雇员":
16
17 Console.WriteLine("早上好!你可以开始工作了!");
18
19 break;
20
21 default:
22
23 Console.WriteLine("早上好!祝你好运!");
24
25 break;
26
27 }
28
29 }
30
31 }

与Java中的switch不同,C#的switch语句要求每一个case块或者在块的末尾提供一个break语句,或者用goto转到switch内的其他case标签。

2.5、foreach语句

foreach语句枚举集合中的各个元素,为集合中的每一个元素执行一次代码块。请参见下面的例子。

 1 using System;
 2
 3 public class Hello {
 4
 5 public static void Main(String[] args) {
 6
 7 foreach (String arg in args)
 8
 9 Console.WriteLine(arg);
10
11 }
12
13 }

如果在运行这个执行文件的时候指定了参数,比如“Hello Peter Kevin Richard”,则程序的输出将是下面几行文字:

Peter

Kevin

Richard

2.6、C#没有>>>移位操作符

C#支持uint和ulong之类的无符号变量类型。因此,在C#中,右移操作符(即“>>”)对于无符号变量类型和带符号变量类型(比如int和long)的处理方式不同。右移uint和ulong丢弃低位并把空出的高位设置为零;但对于int和long类型的变量,“>>”操作符丢弃低位,同时,只有当变量值是正数时,“>>”才把空出的高位设置成零;如果“>>”操作的是一个负数,空出的高位被设置成为1。

Java中不存在无符号的变量类型。因此,我们用“>>>”操作符在右移时引入负号位;否则,使用“>>”操作符。

2.7、goto关键词

Java不用goto关键词。在C#中,goto允许你转到指定的标签。不过,C#以特别谨慎的态度对待goto,比如它不允许goto转入到语句块的内部。在Java中,你可以用带标签的语句加上break或continue取代C#中的goto。

2.8、声明数组

在Java中,数组的声明方法非常灵活,实际上有许多种声明方法都属于合法的方法。例如,下面的几行代码是等价的:

1 int[] x = { 0, 1, 2, 3 };
2
3 int x[] = { 0, 1, 2, 3 };

但在C#中,只有第一行代码合法,[]不能放到变量名字之后。

2.9、包

在C#中,包(Package)被称为名称空间。把名称空间引入C#程序的关键词是“using”。例如,“using System;”这个语句引入了System名称空间。

然而,与Java不同的是,C#允许为名称空间或者名称空间中的类指定别名:

 1 using TheConsole = System.Console;
 2
 3 public class Hello {
 4
 5 public static void Main() {
 6
 7 TheConsole.WriteLine("使用别名");
 8
 9 }
10
11 }

虽然从概念上看,Java的包类似于.NET的名称空间。然而,两者的实现方式不同。在Java中,包的名字同时也是实际存在的实体,它决定了放置.java文件的目录结构。在C#中,物理的包和逻辑的名称之间是完全分离的,也就是说,名称空间的名字不会对物理的打包方式产生任何影响。在C#中,每一个源代码文件可以从属于多个名称空间,而且它可以容纳多个公共类。

.NET中包的实体称为程序集(Assembly)。每一个程序集包含一个manifest结构。manifest列举程序集所包含的文件,控制哪些类型和资源被显露到程序集之外,并把对这些类型和资源的引用映射到包含这些类型与资源的文件。程序集是自包含的,一个程序集可以放置到单一的文件之内,也可以分割成多个文件。.NET的这种封装机制解决了DLL文件所面临的问题,即臭名昭著的DLL Hell问题。

2.10、默认包

在Java中,java.lang包是默认的包,它无需显式导入就已经自动包含。例如,要把一些文本输出到控制台,你可以使用下面的代码:

System.out.println("Hello world from Java");

C#中不存在默认的包。如果要向控制台输出文本,你使用System名称空间Console对象的WriteLine方法。但是,你必须显式导入所有的类。代码如下:

 1 using System;
 2
 3 public class Hello {
 4
 5 public static void Main() {
 6
 7 Console.WriteLine("Hello world from C#");
 8
 9 }
10
11 }

2.11、面向对象

Java和C#都是完全面向对象的语言。在面向对象编程的三大原则方面,这两种语言接近得不能再接近。

  • 继承:这两种语言都支持类的单一继承,但类可以实现多个接口。所有类都从一个公共的基类继承。
  • 封装与可见性:无论是在Java还是C#中,你都可以决定类成员是否可见。除了C#的internal访问修饰符之外,两者的可见性机制非常相似。
  • 多态性:Java和C#都支持某些形式的多态性机制,且两者实现方法非常类似。

2.12、可访问性

类的每个成员都有特定类型的可访问性。C#中的访问修饰符与Java中的基本对应,但多出了一个internal。简而言之,C#有5种类型的可访问性,如下所示:

  • public:成员可以从任何代码访问。
  • protected:成员只能从派生类访问。
  • internal:成员只能从同一程序集的内部访问。
  • protected internal:成员只能从同一程序集内的派生类访问。
  • private:成员只能在当前类的内部访问。

2.13、派生类

在Java中,我们用关键词“extends”实现继承。C#采用了C++的类派生语法。例如,下面的代码显示了如何派生父类Control从而创建出新类Button:

public class Button: Control { . . }

2.14、最终类

由于C#中不存在final关键词,如果想要某个类不再被派生,你可以使用sealed关键词,如下例所示:

sealed class FinalClass { . . }

2.15、接口

接口这个概念在C#和Java中非常相似。接口的关键词是interface,一个接口可以扩展一个或者多个其他接口。按照惯例,接口的名字以大写字母“I”开头。下面的代码是C#接口的一个例子,它与Java中的接口完全一样:

interface IShape { void Draw(); }

扩展接口的语法与扩展类的语法一样。例如,下例的IRectangularShape接口扩展IShape接口(即,从IShape接口派生出IRectangularShape接口)。

interface IRectangularShape: IShape { int GetWidth(); }

如果你从两个或者两个以上的接口派生,父接口的名字列表用逗号分隔,如下面的代码所示:

interface INewInterface: IParent1, IParent2 { }

然而,与Java不同,C#中的接口不能包含域(Field)。

另外还要注意,在C#中,接口内的所有方法默认都是公用方法。在Java中,方法声明可以带有public修饰符(即使这并非必要),但在C#中,显式为接口的方法指定public修饰符是非法的。

2.16、is和as操作符

C#中的is操作符与Java中的instanceof操作符一样,两者都可以用来测试某个对象的实例是否属于特定的类型。在Java中没有与C#中的as操作符等价的操作符。as操作符与is操作符非常相似,但它更富有“进取心”:如果类型正确的话,as操作符会尝试把被测试的对象引用转换成目标类型;否则,它把变量引用设置成null。

为正确理解as操作符,首先请考虑下面这个例子中is操作符的运用。这个例子包含一个IShape接口,以及两个实现了IShape接口的类Rectangle和Circle。

 1 using System;
 2
 3 interface IShape {
 4
 5 void draw();
 6
 7 }
 8
 9 public class Rectangle: IShape {
10
11 public void draw() {
12
13 }
14
15 public int GetWidth() {
16
17 return 6;
18
19 }
20
21 }
22
23 public class Circle: IShape {
24
25 public void draw() {
26
27 }
28
29 public int GetRadius() {
30
31 return 5;
32
33 }
34
35 }
36
37 public class LetsDraw {
38
39 public static void Main(String[] args) {
40
41 IShape shape = null;
42
43 if (args[0] == "rectangle") {
44
45 shape = new Rectangle();
46
47 }
48
49 else if (args[0] == "circle") {
50
51 shape = new Circle();
52
53 }
54
55 if (shape is Rectangle) {
56
57 Rectangle rectangle = (Rectangle) shape;
58
59 Console.WriteLine("Width : " + rectangle.GetWidth());
60
61 }
62
63 if (shape is Circle) {
64
65 Circle circle = (Circle) shape;
66
67 Console.WriteLine("Radius : " + circle.GetRadius());
68
69 }
70
71 }
72
73 }

编译好代码之后,用户可以输入“rectangle”或者“circle”作为Main方法的参数。如果用户输入的是“circle”,则shape被实例化成为一个Circle类型的对象;反之,如果用户输入的是“rectangle”,则shape被实例化成为Rectangle类型的对象。随后,程序用is操作符测试shape的变量类型:如果shape是一个矩形,则shape被转换成为Rectangle对象,我们调用它的GetWidth方法;如果shape是一个圆,则shape被转换成为一个Circle对象,我们调用它的GetRadius方法。

如果使用as操作符,则上述代码可以改成如下形式:

 1 using System;
 2
 3 interface IShape {
 4
 5 void draw();
 6
 7 }
 8
 9 public class Rectangle: IShape {
10
11 public void draw() {
12
13 }
14
15 public int GetWidth() {
16
17 return 6;
18
19 }
20
21 }
22
23 public class Circle: IShape {
24
25 public void draw() {
26
27 }
28
29 public int GetRadius() {
30
31 return 5;
32
33 }
34
35 }
36
37 public class LetsDraw {
38
39 public static void Main(String[] args) {
40
41 IShape shape = null;
42
43 if (args[0] == "rectangle") {
44
45 shape = new Rectangle();
46
47 }
48
49 else if (args[0] == "circle") {
50
51 shape = new Circle();
52
53 }
54
55 Rectangle rectangle = shape as Rectangle;
56
57 if (rectangle != null) {
58
59 Console.WriteLine("Width : " + rectangle.GetWidth());
60
61 }
62
63 else {
64
65 Circle circle = shape as Circle;
66
67 if (circle != null)
68
69 Console.WriteLine("Radius : " + circle.GetRadius());
70
71 }
72
73 }
74
75 }

在上面代码的粗体部分中,我们在没有测试shape对象类型的情况下,就用as操作符把shape转换成Rectangle类型的对象。如果shape正好是一个Rectangle,则shape被转换成为Rectangle类型的对象并保存到rectangle变量,然后我们调用它的GetWidth方法。如果这种转换失败,则我们进行第二次尝试。这一次,shape被转换成为Circle类型的对象并保存到circle变量。如果shape确实是一个Circle对象,则circle现在引用了一个Circle对象,我们调用它的GetRadius方法。

2.17、库

C#没有自己的类库。但是,C#共享了.NET的类库。当然,.NET类库也可以用于其他.NET语言,比如VB.NET或者JScript.NET。值得一提的是StringBuilder类,它是对String类的补充。StringBuilder类与Java的StringBuffer类非常相似。

2.18、垃圾收集

C++已经让我们认识到手工管理内存是多么缺乏效率和浪费时间。当你在C++中创建了一个对象,你就必须手工地拆除这个对象。代码越复杂,这个任务也越困难。Java用垃圾收集器来解决这个问题,由垃圾收集器搜集不再使用的对象并释放内存。C#同样采用了这种方法。应该说,如果你也在开发一种新的OOP语言,追随这条道路是一种非常自然的选择。C#仍旧保留了C++的内存手工管理方法,它适合在速度极端重要的场合使用,而在Java中这是不允许的。

2.19、异常处理

如果你听说C#使用与Java相似的异常处理机制,你不会为此而惊讶,对吧?在C#中,所有的异常都从一个名为Exception的类派生(听起来很熟悉?)另外,正如在Java中一样,你还有熟悉的try和catch语句。Exception类属于.NET System名称空间的一部分。

三、Java没有的功能

C#出生在Java成熟之后,因此,C#拥有一些Java(目前)还没有的绝妙功能也就不足为奇。

3.1、枚举器

枚举器即enum类型(Enumerator,或称为计数器),它是一个相关常量的集合。精确地说,enum类型声明为一组相关的符号常量定义了一个类型名字。例如,你可以创建一个名为Fruit(水果)的枚举器,把它作为一个变量值的类型使用,从而把变量可能的取值范围限制为枚举器中出现的值。

 1 public class Demo {
 2
 3 public enum Fruit {
 4
 5 Apple, Banana, Cherry, Durian
 6
 7 }
 8
 9 public void Process(Fruit fruit) {
10
11 switch (fruit) {
12
13 case Fruit.Apple:
14
15 ...
16
17 break;
18
19 case Fruit.Banana:
20
21 ...
22
23 break;
24
25 case Fruit.Cherry:
26
27 ...
28
29 break;
30
31 case Fruit.Durian:
32
33 ...
34
35 break;
36
37 }
38
39 }
40
41 }

在上例的Process方法中,虽然你可以用int作为myVar变量的类型,但是,使用枚举器Fruit之后,变量的取值范围限制到了Applet、Banana、Cherry和Durian这几个值之内。与int相比,enum的可读性更好,自我说明能力更强。

3.2、结构

结构(Struct)与类很相似。然而,类是作为一种引用类型在堆中创建,而结构是一种值类型,它存储在栈中或者是嵌入式的。因此,只要谨慎运用,结构要比类快。结构可以实现接口,可以象类一样拥有成员,但结构不支持继承。

然而,简单地用结构来取代类可能导致惨重损失。这是因为,结构是以值的方式传递,由于这种传递方式要把值复制到新的位置,所以传递一个“肥胖的”结构需要较大的开销。而对于类,传递的时候只需传递它的引用。

下面是一个结构的例子。注意它与类非常相似,只要把单词“struct”替换成“class”,你就得到了一个类。

 1 struct Point {
 2
 3 public int x, y;
 4
 5 public Point(int x, int y) {
 6
 7 this.x = x;
 8
 9 this.y = y;
10
11 }
12
13 }

3.3、属性

C#类除了可以拥有域(Field)之外,它还可以拥有属性(Property)。属性是一个与类或对象关联的命名的特征。属性是域的一种自然扩展——两者都是有类型、有名字的类成员。然而,和域不同的是,属性不表示存储位置;相反,属性拥有存取器(accessor),存取器定义了读取或者写入属性值时必须执行的代码。因此,属性提供了一种把动作和读取、写入对象属性值的操作关联起来的机制,而且它们允许属性值通过计算得到。

3.4、以引用方式传递简单数据类型的参数

在Java中,当你把一个简单数据类型的值作为参数传递给方法时,参数总是以值的方式传递——即,系统将为被调用的方法创建一个参数值的副本。在C#中,你可以用引用的方式传递一个简单数据类型的值。此时,被调用的方法将直接使用传递给它的那个值——也就是说,如果在被调用方法内部修改了参数的值,则原来的变量值也随之改变。

在C#中以引用方式传递值时,我们使用ref关键词。例如,如果编译并运行下面的代码,你将在控制台上看到输出结果16。注意i值被传递给ProcessNumber之后是如何被改变的。

 1 using System;
 2
 3 public class PassByReference {
 4
 5 public static void Main(String[] args) {
 6
 7 int i = 8;
 8
 9 ProcessNumber(ref i);
10
11 Console.WriteLine(i);
12
13 }
14
15 public static void ProcessNumber(ref int j) {
16
17 j = 16;
18
19 }
20
21 }

C#中还有一个允许以引用方式传递参数的关键词out,它与ref相似。但是,使用out时,作为参数传递的变量在传递之前不必具有已知的值。在上例中,如果整数i在传递给ProcessNumber方法之前没有初始化,则代码将出错。如果用out来取代ref,你就可以传递一个未经初始化的值,如下面这个修改后的例子所示。

 1 using System;
 2
 3 public class PassByReference {
 4
 5 public static void Main(String[] args) {
 6
 7 int i;
 8
 9 ProcessNumber(out i);
10
11 Console.WriteLine(i);
12
13 }
14
15 public static void ProcessNumber(out int j) {
16
17 j = 16;
18
19 }
20
21 }

经过修改之后,虽然i值在传递给ProcessNumber方法之前没有初始化,但PassByReference类能够顺利通过编译。

3.5、C#保留了指针

对于那些觉得自己能够恰到好处地运用指针并乐意手工进行内存管理的开发者来说,在C#中,他们仍旧可以用既不安全也不容易使用的“古老的”指针来提高程序的性能。C#提供了支持“不安全”(unsafe)代码的能力,这种代码能够直接操作指针,能够“固定”对象以便临时地阻止垃圾收集器移动对象。无论从开发者还是用户的眼光来看,这种对“不安全”代码的支持其实是一种安全功能。“不安全”的代码必须用unsafe关键词显式地标明,因此开发者不可能在无意之中使用“不安全”的代码。同时,C#编译器又和执行引擎协作,保证了“不安全”的代码不能伪装成为安全代码。

 1 using System;
 2
 3 class UsePointer {
 4
 5 unsafe static void PointerDemo(byte[] arr) {
 6
 7 .
 8
 9 .
10
11 }
12
13 }

C#中的unsafe代码适合在下列情形下使用:当速度极端重要时,或者当对象需要与现有的软件(比如COM对象或者DLL形式的C代码)交互时。

3.6、代理

代理(delegate)可以看作C++或者其他语言中的函数指针。然而,与函数指针不同的是,C#中的代理是面向对象的、类型安全的、可靠的。而且,函数指针只能用来引用静态函数,但代理既能够引用静态方法,也能够引用实例方法。代理用来封装可调用方法。你可以在类里面编写方法并在该方法上创建代理,此后这个代理就可以被传递到第二个方法。这样,第二个方法就可以调用第一个方法。

代理是从公共基类System.Delegate派生的引用类型。定义和使用代理包括三个步骤:声明,创建实例,调用。代理用delegate声明语法声明。例如,一个不需要参数且没有返回值的代理可以用如下代码声明:

delegate void TheDelegate();

创建代理实例的语法是:使用new关键词,并引用一个实例或类方法,该方法必须符合代理指定的特征。一旦创建了代理的实例,我们就可以用调用方法的语法调用它。

3.7、包装和解除包装

在面向对象的编程语言中,我们通常使用的是对象。但为了提高速度,C#也提供了简单数据类型。因此,C#程序既包含一大堆的对象,又有大量的值。在这种环境下,让这两者协同工作始终是一个不可回避的问题,你必须要有一种让引用和值进行通信的方法。

在C#以及.NET运行时环境中,这个“通信”问题通过包装(Boxing)和解除包装(Unboxing)解决。包装是一种让值类型看起来象引用类型的处理过程。当一个值类型(简单数据类型)被用于一个要求或者可以使用对象的场合时,包装操作自动进行。包装一个value-type值的步骤包括:分配一个对象实例,然后把value-type值复制到对象实例。

解除包装所执行的动作与包装相反,它把一个引用类型转换成值类型。解除包装操作的步骤包括:首先检查并确认对象实例确实是给定value-type的一个经过包装的值,然后从对象实例复制出值。

Java对该问题的处理方式略有不同。Java为每一种简单数据类型提供了一个对应的类封装器。例如,用Integer类封装int类型,用Byte类封装byte类型。

【结束语】本文为你比较了C#和Java。这两种语言很相似,然而,说C#是Java的克隆或许已经大大地言过其实。面向对象、中间语言这类概念并不是什么新东西。如果你准备设计一种面向对象的新语言,而且它必须在一个受管理的安全环境内运行,你难道不会搞出与C#差不多的东西吗?

时间: 2024-10-09 21:26:37

[转] C#与Java的比较的相关文章

Java多线程学习(吐血超详细总结)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程

Java TM 已被阻止,因为它已过时需要更新的解决方法

公司的堡垒机需要通过浏览器登陆,且该堡垒机的网站需要Java的支持,最近通过浏览器登陆之后总是提示"java TM 已被阻止,因为它已过时需要更新的解决方法"导致登陆之后不能操作, 但是操作系统中确实已经安装了比较新的JDK,安装的JDK版本是jdk-7u67-windows-i586,因为太烦人,所以决定搞清楚报错的原因,一劳永逸,彻底解决这个问题 准备工作:安装JDK,安装版本jdk-7u67-windows-i586.exe,因为机器的Eclipse还依赖64位的JDK,所以另安

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new

由@NotNull 注解引出的关于Java空指针的控制(转)

Java 小技巧和在java应用避免NullPonintException的最佳方法 在java应用程序中,一个NullPonintException(空指针异常)是最好解决(问题)的方法.同时,空指针也是写健壮的顺畅运行的代码的关键.“预防好过治疗”这句话也同样适用于令人不爽的NullPonintException.通过应用防御性的编码技术和在遵守多个部分之间的约定,你可以再很大程度上避免NullPointException.下面的这些java小技巧可以最小化像!=null这种检查的代码.作为

Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)

如果没有用来读取注解的工具,那注解将基本没有任何作用,它也不会比注释更有用.读取注解的工具叫作注解处理器.Java提供了两种方式来处理注解:第一种是利用运行时反射机制:另一种是使用Java提供的API来处理编译期的注解. 反射机制方式的注解处理器 仅当定义的注解的@Retention为RUNTIME时,才能够通过运行时的反射机制来处理注解.下面结合例子来说明这种方式的处理方法. Java中的反射API(如java.lang.Class.java.lang.reflect.Field等)都实现了接

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

Java注解(1)-注解基础

注解(Annotation)是在JAVA5中开始引入的,它为在代码中添加信息提供了一种新的方式.注解在一定程度上把元数据与源代码文件结合在一起,正如许多成熟的框架(Spring)所做的那样.那么,注解到底可以做什么呢? 1.注解的作用. 提供用来完整地描述程序所需要的信息,如编译期校验程序信息. 生成描述符文件,或生成新类的定义. 减轻编写"样板"代码(配置文件)的负担,可以使用注解自动生成. 更加干净易读的代码. 编译期类型检查. 2.Java提供的注解 Java5内置了一些原生的注

异常笔记--java编程思想

开一个新的系列,主要记一些琐碎的重要的知识点,把书读薄才是目的...特点: 代码少,概念多... 1. 基本概念 异常是在当前环境下无法获得必要的信息来解决这个问题,所以就需要从当前环境跳出,就是抛出异常.抛出异常后发生的几件事: 1.在堆上创建异常对象. 2.当前的执行路径中止                                          3. 当前环境抛出异常对象的引用.                                         4. 异常处理机制接

Java自学序言

Java自学序言 亲爱的自己和各位读者朋友: 您们好! 这是作者本人自学Java编程开发的一系列文章,不具有一定的权威性,也算是自己一个人的学习笔记和总结,希望自己通过博客的形式将我自己的学习效率得到提高.如自学的稳重存在不足或错误的地方希望广大的博客朋友们多多指教.本人在此不胜感激! 学习Java是一件很痛苦的事儿,我自己要想不断的去挑战一下自己,把自己大学所学的Java知识能够巩固起来.不断的去改正自己开发中的不足之处.如何来学习Java?如何来更好的掌握Java开发语言?这些都是我们要不断

接口测试(java+testng+ant+jenkins)第五篇 java二

1.数据代码分离,方便维护. 一般做法是将数据保存在excel,通过程序读取. 2.读取excel数据. 在D盘新建excel,A列放url,B列放参数. 新建class redExcel package com.lx; import java.io.File; import java.io.IOException; import jxl.*; import jxl.read.biff.BiffException; public class redExcel{ public static voi