简易版本,默认学过 C++,没写就是一样
java 程序是一系列对象的集合,是通过对象间的调用来协同的,所有的代码都必须封装到类中
大小写敏感
# 命名规范
1、 项目名全部小写
2、 包名全部小写
3、 类名首字母大写,如果类名由多个单词组成,每个单词的首字母都要大写。如:public class MyFirstClass{}
4、 变量名、方法名首字母小写,如果名称由多个单词组成,每个单词的首字母都要大写。
5、 常量名全部大写
PS:java 的标识符要求与 C++ 大致相同,不过 java 的可以是中文
# 注释规范
1、类注释
在每个类前面必须加上类注释,注释模板如下:
/** | |
* Copyright (C), 2006-2010, ChengDu Lovo info. Co., Ltd. | |
* FileName: Test.java | |
* 类的详细说明 | |
* | |
* @author 类创建者姓名 | |
* @Date 创建日期 | |
* @version 1.00 | |
*/ |
2、属性注释
在每个属性前面必须加上属性注释,注释模板如下:
/** 提示信息 */ | |
private String strMsg = null; |
3、方法注释
在每个方法前面必须加上方法注释,注释模板如下:
/** | |
* 类方法的详细使用说明 | |
* | |
* @param 参数 1 参数 1 的使用说明 | |
* @return 返回结果的说明 | |
* @throws 异常类型。错误代码 注明从此类方法中抛出异常的说明 | |
*/ | |
throws是用来声明一个方法可能抛出的异常,而且不做任何处理就上传 | |
throw抛出具体异常,需要自行处理或者throws给他人 |
4、构造方法注释
在每个构造方法前面必须加上注释,注释模板如下:
/** | |
* 构造方法的详细使用说明 | |
* | |
* @param 参数 1 参数 1 的使用说明 | |
* @throws 异常类型。错误代码 注明从此类方法中抛出异常的说明 | |
*/ |
5、方法内部注释
在方法内部使用单行或者多行注释,该注释根据实际情况添加。
如:
// 背景颜色 | |
Color bgColor = Color.RED |
# java 特点
访问修饰符会多出一个 default
非访问修饰符(类似于 static 这种)则有
final,abstract,static,synchronized
const 作为关键字,但只是保留关键字,不能使用
null 不作为关键字,而是和 true,false 一样是个字面常量,不可以做标识符
由于 java 是对象的集合,所以程序入口并不是 main 函数,而是一个 main 方法:
public static void main(String[] arg) |
你必须在某一个类中定义它,且这个类必须是 public
java 并不能像 C++ 一样,一个访问权限放在一块定义,只能每个都单独写
# 基础语法
一个完整的 java 程序,应该包括:
package javawork.helloworld; | |
/* 把编译生成的所有.class 文件放在指定包中,java 的类都是单个的字节文件 | |
而且文件名还和类名相同,为避免冲突,使用包来管理 | |
类名空间 | |
*/ | |
import java awt.*; | |
// 告诉编译器本程序使用到了系统的 AWT 包 | |
public class HelloWorldApp{...} | |
class FirstClass {...}; | |
interface FirstInterface{} | |
// 定义接口 |
其中形如 java.io.*
实际上是指 java_installation/java/io
路径下的类
# 基本数据类型
一共八种:byte,short,int,long,float,double,boolean,char
可以在值后加对应首字母区分,理论上这里不区分大小写,但是 l 建议大写
byte:
只有 8 位的整数,使用补码表示,所以范围是 - 128 到 127
boolean 的默认值是 false
# 变量类型
由于全部都要类封装,没有全局变量:
局部变量变成了在类的方法中声明的变量(定义是必须初始化,可以是值,表达式或者方法)
直接在类中(无修饰)的则称为
成员变量(实例变量),定义中不能给值,他们属于类的实例,而不属于类本身。实例如果不初始化实例变量,则为默认值(引用的默认值是 NULL)
** 静态变量(类变量)** 和 C++ 差不多,共享且只初始化一次,声明周期是整个程序,你可以当成是全局变量,属于类
参数变量 所谓的形参,同样可以是值 / 引用传递
局部变量存储在 JVM 的栈上,但是实例变量以及对象本身在堆上(java 中使用 new 关键字来创建对象,而 new 在 C 中用于动态分配空间,所以这种写法如果用在 C 上,也是在堆上)
局部变量是该方法私有的,其他方法不能直接访问
常量 用 final
修饰
示例:
public class AppConfig { | |
public static final String APP_NAME = "MyApp"; | |
public static final String APP_VERSION = "1.0.0"; | |
public static final String DATABASE_URL = "jdbc:mysql://localhost:3306/mydb"; | |
public static void main(String[] args) { | |
System.out.println("Application name: " + AppConfig.APP_NAME); | |
System.out.println("Application version: " + AppConfig.APP_VERSION); | |
System.out.println("Database URL: " + AppConfig.DATABASE_URL); | |
} | |
} |
# 访问控制修饰符
需要说明,这里的 protected 和 C++ 不一样,java 中只有类与类之间的关系,而且即使这样,也是不一样的:
java 的 protected 比 C++ 更为复杂,但是却相对宽松
package p1; | |
public class Father1 { | |
protected void f() {} // 父类 Father1 中的 protected 方法 | |
} | |
package p1; | |
public class Son1 extends Father1 {} | |
package p11; | |
public class Son11 extends Father1{} | |
package p1; | |
public class Test1 { | |
public static void main(String[] args) { | |
Son1 son1 = new Son1(); | |
son1.f(); // Compile OK ----(1) | |
son1.clone(); // Compile Error ----(2) | |
Son11 son = new Son11(); | |
son11.f(); // Compile OK ----(3) | |
son11.clone(); // Compile Error ----(4) | |
} | |
} |
注意:在 C++ 中,以上类似的写法没有一个会编译成功
clone () 是 Object 类的 protected 方法,用于复制一个对象,所有对象都默认继承该类(除非声明了继承其他类)
protected 的访问权限不只与继承有关,还与包有关。
按照 C 的规则,Test1 不是其子类,对于 Son1 来说完全是外部,f () 作为保护对象应该是无法访问的,但是 JAVA 不同,只要是同包就可以访问 protected(protected 不能修饰外部类),只有异包才会像 C 那样严格(所以 clone 不能访问,但是如果 father1 重写了 clone 就可以)。
JAVA 的 protected 是与包有关的,但是 C++ 的却与命名空间没有任何关系,更为严格。
总之:
Java 的 protected
本质上是 " 包内公开 + 跨包子类可访问 " 的混合权限,而 C++ 的 protected
是 " 仅类自身及派生类内部可访问(且仅限当前实例)" 的严格权限
也就是如果只限制在一个包内,Java 的 protected 和 public 没有区别
package p2; | |
class MyObject2 { | |
protected Object clone() throws CloneNotSupportedException{ | |
return super.clone(); | |
} | |
} | |
package p22; | |
public class Test2 extends MyObject2 { | |
public static void main(String args[]) { | |
MyObject2 obj = new MyObject2(); | |
obj.clone(); // Compile Error ----(1) | |
Test2 tobj = new Test2(); | |
tobj.clone(); // Complie OK ----(2) | |
} | |
} |
Java 的跨包子类只能通过自身或者自身子类的实例来访问父类 protected
<del> 这一点也和 C++ 的继承一样,没差 </del>
有一次比较奇怪的情况:
package p3; | |
class MyObject3 extends Test3 { | |
} | |
package p33; | |
public class Test3 { | |
public static void main(String args[]) { | |
MyObject3 obj = new MyObject3(); | |
obj.clone(); // Compile OK ------(1) | |
} | |
} | |
//clone 继承自 Test3, 而执行又恰好是在 Test3 中,相当于在父类里执行子类继承的父类函数,所以说在是可以通过自身以及自身子类的实例来访问(此时的自身,就是指父类 Test3) |
但是:
package p4; | |
class MyObject4 extends Test4 { | |
protected Object clone() throws CloneNotSupportedException { | |
return super.clone(); | |
} | |
} | |
package p44; | |
public class Test4 { | |
public static void main(String args[]) { | |
MyObject4 obj = new MyObject4(); | |
obj.clone(); // Compile Error -----(1) | |
} | |
} | |
// 由于 MyObject4 重写了 clone,clone 来源于 MyObject4, 而 Test4 是其父类而不是子类,所以不能访问,这相当于在父类中执行子类函数。 |
所以理解下:
# 非访问修饰符
static:修饰方法和变量
final:修饰类,方法和变量,使用 final 修饰的类不能够被继承,被修饰的方法不可以被子类重定义,修饰的变量是常量(通常和 static 连用)
abstract:用于创建抽象类和方法,类似于 C++virtual 的虚基类和虚函数
synchronized,volatile:用于线程编程,前者表示这个方同时只能有一个线程访问,后者表示其修饰的变量将在所有进程间共享,这使得所有线程看到的这个变量的值都是相同的
transient:其修饰的变量值不会在序列化时保存,而是使用默认值
抽象方法不能是 final 或者 static,抽象类可以不含抽象方法,但是有抽象方法的类必须是抽象类,所有非抽象类的子类必须实现抽象方法,除非它也是抽象类。
PS:C++ 中可以在非虚基类中定义虚函数,因为虚函数本身是为了实现多态性,虚基类是避免菱形继承带来的变量重复。而抽象类和抽象方法是通过继承和方法重写在子类中强制实现某种方法,Java 的多态则是通过接口。
# 循环
# 增强 for 循环
public class Test{ | |
public static void main(String[] args){ | |
int [] numbers={20,30,40,50}; | |
for (int x:numbers){ | |
System.out.print(x); | |
System.out.print(","); | |
} | |
System.out.print("\n"); | |
} | |
} |
# switch-case
case 如果没有 break,不是顺序执行下去,而是继续匹配,没有就直接到 default
# Number,Math 类
当内置数据类型作为对象使用时,使用的是 Java 内置的类。
将内置类型转换为对应的包装类,这个操作称为装箱
反之,也可以从对象中拆箱出内置类型
(JAVA5 之后自动拆装)
自带的:
public class Test{ | |
public static void main(String[] args){ | |
Integer x = 5; // 装箱 | |
x = x + 10; // 拆箱 | |
System.out.println(x); | |
} | |
} |
# Number 类
定义:
public abstract class Number implements Serializable { | |
// 抽象方法 | |
public abstract int intValue(); | |
public abstract long longValue(); | |
public abstract float floatValue(); | |
public abstract double doubleValue(); | |
// Java 8 新增 | |
public byte byteValue() { | |
return (byte)intValue(); | |
} | |
public short shortValue() { | |
return (short)intValue(); | |
} | |
} |
你可以直接使用这个 Number 类
Number num = 1234.56; // 实际是 Double 类型 | |
System.out.println(num.intValue()); // 1234 (截断小数) | |
System.out.println(num.longValue()); // 1234 | |
System.out.println(num.floatValue()); // 1234.56 | |
System.out.println(num.doubleValue()); // 1234.56 |
比较时需要用方法来转换为同一类型。
此时格式化输出是靠这些类的方法,也有特殊的数值处理。
BigInterger bigint=new BigIntger("12345678901234567890"); | |
BigDecimal bigdec=new BigDecimal("1234567890.1234567890"); | |
BigInterger sum=bigint.add(new BigInteger"1"); | |
BigDecimal product=bigdec.mutiply(new BigDecimal("2")) |
NumerFormat nf=NumberFormat.getInstance(); | |
nf.setMaximunFractionDigits(2); | |
System.out.println(nf.format(1234.5678)); | |
// 输出 1234.57 |
# Math 类
public class Test { | |
public static void main (String []args) | |
{ | |
System.out.println("90 度的正弦值:" + Math.sin(Math.PI/2)); | |
System.out.println("0度的余弦值:" + Math.cos(0)); | |
System.out.println("60度的正切值:" + Math.tan(Math.PI/3)); | |
System.out.println("1的反正切值: " + Math.atan(1)); | |
System.out.println("π/2的角度值:" + Math.toDegrees(Math.PI/2)); | |
System.out.println(Math.PI); | |
} | |
} |