最近在学习 java,总结些东西方便记忆,后续可以提供给会 C# 开发,并想学习 Java 的同学们参考。 很多语法都是简单的星星点点的示例,要好好掌握这门语言,还是需要自己系统去详细学习下。 切记,作为一名研发,不要因为语言而限制住你的发展!~~
//C#
int[] array = new int[] { 1, 2, 3, 7, 8, 9 };
foreach (int item in array)
{
Console.WriteLine(item);
}
//Java
int[] array = new int[]{1, 2, 3, 7, 8, 9};
for (int item : array) {
System.out.println(item);
}
- 需要注意的是 protected,java 和 C# 是有区别的。
C# :
访问权限 | 说明 |
---|---|
public | 访问不受限制 |
protected | 访问限于包含类或派生自包含类的类型 |
Internal | 访问限于当前程序集 |
protected internal | 访问限于当前程序集或派生自包含类的类型 |
private | 访问限于包含类 |
Java :
访问权限 | 同类 | 同包不同类(不含子类) | 同包子类 | 不同包不同类(不含子类) | 不同包子类 |
---|---|---|---|---|---|
public | ∨ | ∨ | ∨ | ∨ | ∨ |
protected | ∨ | ∨ | ∨ | × | ∨ |
无(default) | ∨ | ∨ | ∨ | × | × |
private | ∨ | × | × | × | × |
C#只允许一个无参构造函数;java可以有多个静态块,并且按照指定的顺序执行。
//C#
class Birds
{
public static bool isVertebrate;
public static bool isOvipara;
static Birds()
{
isVertebrate = true;
isOvipara = true;
}
}
//Java
class Birds {
public static Boolean isVertebrate;
public static Boolean isOvipara;
static{
isVertebrate = true;
}
static{
isOvipara = true;
}
}
C# 的静态字段和常量都可以被子类访问,java 的静态 final 一样可以被子类访问。 注意的是 Java 的构造函数里的 this、 super 必须在代码第一行。
//C#
class Birds
{
public const int WingsNumber = 2;
public static readonly int PawsNumber = 2;
protected string color = null;
protected bool canSwim;
public Birds()
: this(null)
{
}
public Birds(String color)
{
this.color = color;
this.canSwim = false;
}
public Birds(String color, Boolean canSwim)
{
this.color = color;
this.canSwim = canSwim;
}
}
class Duck : Birds
{
public Duck()
: this(null)
{
//some code
}
public Duck(String color)
: this(color, true)
{
//some code
}
public Duck(String color, Boolean canSwim)
: base(color, canSwim)
{
//some code
}
}
//Java
class Birds {
public final static int WingsNumber = 2;
public final int PawsNumber = 2;
protected String color = null;
protected Boolean canSwim ;
public Birds() {
this(null);
}
public Birds(String color) {
this.color = color;
this.canSwim = false;
}
public Birds(String color, Boolean canSwim) {
this.color = color;
this.canSwim = canSwim;
}
}
class Duck extends Birds{
public Duck() {
this(null);
//some code
}
public Duck(String color) {
this(color, true);
//some code
}
public Duck(String color, Boolean canSwim) {
super(color, canSwim);
//some code
}
}
在 C# 中,无法通过 class 的实例来访问静态字段和常量
//C#
class Birds
{
public const int WingsNumber = 2;
public static readonly int PawsNumber = 2;
}
public class Program
{
static void Main(string[] args)
{
Console.WriteLine($"wings number:{Birds.WingsNumber}");
Console.WriteLine($"paws number:{Birds.PawsNumber}");
//Console.WriteLine($"paws number:{new Birds().PawsNumber}"); //error
}
}
在 Java 中,static final 字段,可以被 class 的实例访问(这种方式并不推荐)。
//Java
class Birds {
public static final int WingsNumber = 2;
public final int PawsNumber = 2;
}
public class Main {
public static void main(String[] args) {
System.out.println("wings number:" + new Birds().WingsNumber);
System.out.println("wings number:" + Birds.WingsNumber);
System.out.println("paws number:" + new Birds().PawsNumber);
//System.out.println("paws number:" + Birds.PawsNumber); //error
}
}
Java 和 C# 的嵌套类是完全不一样的
C# 的嵌套类的最大用途是控制访问可见性,使用基本上和普通类一样,没什么滑头
//C#
public class Outer
{
private int size = 0;
public class Inner
{
public void someMethod()
{
//size++; //error
}
}
}
public class Program
{
static void Main(string[] args)
{
Outer.Inner inner = new Outer.Inner();
Outer outer = new Outer();
}
}
Java 中的,内部类总是与实例相关联,下面在创建 Inner 类实例的时候用的是 Outer 的实例,outer.new Inner(),所以 Inner 类的实例可以访问 Inner 类的内部字段。
//Java
public class Outer
{
private int size = 0;
public class Inner
{
public void someMethod()
{
size++;
}
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.someMethod();
}
}
java里,嵌套类同名字段作用域
//Java
public class Outer {
private int size = 0;
public Inner createInner(){
return this.new Inner();
}
public int getSize(){
return size;
}
public class Inner {
private int size = 1;
public void someMethod() {
size++;
System.out.println(size); //2
System.out.println(Outer.this.size); //0
}
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.someMethod();
}
}
-
Java 中一个普通类是不可以定义为 static 的,只有内部类可以为静态类。 而 C# 中是可以直接定义一个静态类的。
-
Java 中的静态内部类中可以定义静态成员也可以定义非静态成员,静态成员可以用类名直接访问, 而非静态成员只有 new 一个静态内部类的实例才可以访问到。 Java 静态内部类中只能访问外部类的静态成员,因为如果可以访问外部类的非静态成员,这时候外部类 可能还没有实例化,这时就会出错。
-
c# 中的静态类中只能定义静态成员,且不能 new 一个静态类的实例 。普通类中的静态成员只能用类名进行引用,不能用类的实例进行引用。
下面是java静态类和非静态类的示例
//Java
public class Outer {
private int size = 0;
private static int staticSize = 3;
public Inner createInner(){
return this.new Inner();
}
public int getSize(){
return size;
}
public class Inner {
private int size = 1;
public void someMethod() {
size++;
System.out.println(size);
System.out.println(Outer.this.size);
}
}
public static class StaticInner{
public void someMethod() {
System.out.println(staticSize);
}
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.someMethod();
Outer.StaticInner staticInner = new Outer.StaticInner();
staticInner.someMethod();
}
}
局部类的重要特性
- 局部类仅在定义自身的代码块中是可见和可用的。
- 除了
下面是 Java 中局部类示例,Local 就是一个局部类(ps:有点像 javascript 里的 funtion 玩法)
//Java
public class Outer {
public class Inner {
private int size = 1;
public void someMethod() {
int y = 5;
class Local{
int x = 6;
public void someMethod(){
System.out.println(size);
System.out.println(y);
System.out.println(x);
}
}
new Local().someMethod();
}
}
}
//Java
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Child();
p1.eat();
Person p2 = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p2.eat();
}
}
C# 中有匿名对象,匿名委托,还有 Action 和 Func 等委托对象,这里就不列举了。
Java 的 finally语法存在设计缺陷。 finally 块允许包含一条跳转语句,break、 continue 或 return。 finally 如果有 return 会覆盖catch 里的 throw,同样如果 finally 里有 throw 会覆盖 catch 里的 return。
//Java
class Test{
public Boolean test() throws Exception{
boolean ret = true;
try{
String path = "";
File file = new File(path);
file.createNewFile();
return ret;
}
catch (IOException ex){
System.out.println("catch:" + ex.getMessage());
ret = false;
throw ex;
}
finally {
System.out.println("finally");
}
}
}
public class Main {
public static void main(String[] args) {
boolean res = true;
try{
res = new Test().test();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(res);
}
}
finally
true
Java.io.IOException: 系统找不到指定的路径。
at Java.io.WinNTFileSystem.createFileExclusively(Native Method)
at Java.io.File.createNewFile(File.Java:1012)
at Test.test(Main.Java:126)
at Main.main(Main.Java:59)
下面示例中, finally 中的 return 覆盖了 cache 里的 throw,异常丢了。
//Java
class Test{
public Boolean test() throws Exception{
boolean ret = true;
try{
String path = "";
File file = new File(path);
file.createNewFile();
return ret;
}
catch (IOException ex){
System.out.println("catch:" + ex.getMessage());
ret = false;
throw ex;
}
finally {
System.out.println("finally");
return ret;
}
}
}
public class Main {
public static void main(String[] args) {
boolean res = true;
try{
res = new Test().test();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(res);
}
}
catch:系统找不到指定的路径。
finally
false
下面示例中, finally 中的 throw 覆盖了 cache 里的 return。
//Java
class Test{
public Boolean test() throws Exception{
boolean ret = true;
try{
String path = "";
File file = new File(path);
file.createNewFile();
return ret;
}
catch (IOException ex){
System.out.println("catch:" + ex.getMessage());
return false;
}
finally {
System.out.println("finally");
throw new Exception("throw new exception");
}
}
}
public class Main {
public static void main(String[] args) {
boolean res = true;
try{
res = new Test().test();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(res);
}
}
catch:系统找不到指定的路径。
finally
true
Java.lang.Exception: throw new exception
at Test.test(Main.Java:136)
at Main.main(Main.Java:59)
C# 通过禁止在 finally 块中使用任何跳转语句来避免 Java 中的缺陷。
//C#
class Program
{
static void Main(string[] args)
{
switch(1)
{
case 1:
try { }
catch (Exception ex1) { }
finally
{
break; //error 控制不能离开 finally 子句主体
}
}
try { }
catch (Exception ex1) { }
finally
{
return; //error 控制不能离开 finally 子句主体
}
}
}
J2SE 5.0 引入了 enum,Java 的 enum 其实就是类,可以添加方法、字段,实现接口等。
//Java
enum Converter {
KG("KG") {
@Override
double performConversion(double f) {
return f *= 0.45;
}
},
CARAT("carat") {
@Override
double performConversion(double f) {
return f *= 2267.96;
}
},
GMS("gms") {
@Override
double performConversion(double f) {
return f *= 453.59;
}
}
;
private final String symbol;
Converter(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol.toString();
}
abstract double performConversion(double f);
}
public class Main {
public static void main(String[] args) {
double d = 11.11;
for (Converter conv : Converter.values()) {
System.out.println(conv.toString() + ":" + conv.performConversion(d));
}
}
}
C# 里的 enum 是值类型,并且不能有构造函数,方法等。
//C#
class Program
{
static void Main(string[] args)
{
foreach (Color e in Enum.GetValues(typeof(Color)))
{
Console.WriteLine($"{e}:{(int)e}");
}
}
}
public enum Color
{
Red = 0,
Yellow = 1,
Blue = 3
}
Java的注解规则:
- 使用参数的类型声明方法
- 方法不应包含任何参数
- 方法不应包含任何throws子句
- 方法的返回类型应该为:基本类型、字符串、类、枚举、这些类型的数组
//Java
public @interface Task {
int value() default 0;
String desc() default "";
}
public class Birds {
@Task
public Birds() {
this(null);
}
@Task(123)
public Birds(String color) {
}
@Task(value = 123, desc = "456")
public Birds(String color, Boolean canSwim) {
}
}
C# 的特性就是class,以Attribute为结尾命名,派生于Attribute类
//C#
public class MyAttribute : Attribute
{
public int ID { get; set; }
public string Desc { get; set; }
public void Say()
{
System.Console.WriteLine($"ID:{ID}, Desc:{Desc}");
}
}
class Birds
{
public Birds()
: this(null)
{
}
[My]
public Birds(String color)
{
this.color = color;
this.canSwim = false;
}
[My(ID = 123, Desc = "456")]
public Birds(String color, Boolean canSwim)
{
this.color = color;
this.canSwim = canSwim;
}
}
具体使用都是基于反射原理,这里就不详细说明了。