Java起源
SUN公司的James Gosling亲自设计Java语言,还给他配套了Java编译器和Java虚拟机
首次亮相时间:1995
Java分类
JAVAME 微型版
JAVASE 标准版
JAVAEE 企业版
Java名词
JDK – Java Development Kit(java开发工具包)包含基本类库和开发命令,可以开发java
JVM – JavaVirtual Machine(java 虚拟机)Java语言内部核心
JRE – Java Runtime Environment(java 运行环境)包含基本类库和一些运行命令,可以运行编译好的java 程序
JDK->JRE->JVM
Java特点
- 是纯净版的C++,没有C的头文件,指针,运算符重载等
- 面向对象
- 分布式,适合于网络、分布式环境,可以构建防病毒
- 健壮,跟C++最大的不同在于java采用的指针模型可以消除重写内存和损坏数据的可能性。
- 跨平台,有JVM提供字节码(bytecode)的运行环境,屏蔽底层差异,一次编译,到处运行。
- 垃圾收集,使用new来分配空间,代替动态分配,java系统线程自动处理无用内存空间的垃圾收集
Java程序
public class HelloWorld{
public static void main(String args[]){
System.out.println("Hello,World,LKJ");
}
}
- 输出的应用
– System.out.print(“用print输出i:”+ i);
– System.out.println( “用println输出i:”+ i);
– System.out.printf(“i的值为%d,j的值为%f”, i,j); - 一个源代码文件中可以有很多类,但是只能有一个pubilc的类,并且与文件名称一致,大小写注意,
- 编写代码,生成.java
- 编译.java文件javac,生成.class文件
运行java HelloWorld
编写带包结构程序,package a.b.c,要写在文件第一行
- 编译带包结构程序,要加参数 javac -d
运行带包结构程序,要指定类全名 java a.b.c.HelloWorld
main()括号里加参数arg[]相当于运行命令是后面带的参数。
Java标识符
- 给类,变量,方法命名
- 可以包含’_’ ‘字母’ ‘$’,大小写敏感
不要与关键字冲突,没有长度限制
类名,接口名单词首字母大写 MyClass
- 字段,方法,对象,第一个单词首字母小写,其他单词首字母大写isWoman
- 常量,全部大写
- Java包,全部小写
关键字列表
基本数据类型
- 长整形long变量赋值时腰子数字最后加上l或者是L
- 整形数据,正整数存储原码,负整数存储补码
- 浮点型数值默认double类型
字符串类型
- JDK的一个类
- 字符串要用双引号串起来
- 可以使用 + 运算符拼接字符串,还可连接其他类型数据
引用数据类型
- reference type的变量是所引用的对象的内存地址
- 数组Array,类class,接口interface属于引用数据类型。
Java表达式
常用运算符
- 符号 + 可以进行字符串的连接。
- 任何数据类型(包括基本类型和引用类型)的数据都可以用==或者是!=来比较是否相等,结果返回true或者false。
- &&,||,!这三个只能用于布尔值的运算。存在短路预算
- a = 00110111,则最高位移入0,a>>2 = 00001101
- b = 11010011,则最高位移入1,b>>2 = 11110100
- b = 11010011,无符号右移,最高位都移入0,b>>>2 = 00110100
显式转换和隐式转换
流程控制语句
1 分支语句
- if-else
- switch-case
2 循环语句
- for
- while
- do-while
3 循环跳转语句
- break
- contiune
- label
Java数组
- 数组元素可以是
– 基本数据类型
– 某一类的对象(引用类型) - 建立数组步骤
– 声明数组
– 创建数组空间
– 初始化数组元素
创建数组
- 声明数组:char MyArray[]; 或者是char[] MyArray;
为数组开辟内存空间(必须指明数组长度)MyArray = new char[7];
也可以创建时就赋初值
– char[] MyArray={‘a’,’b’,’c’,’d’,’e’,’f’,’g’};创建一个基本数据类型的数组
- 创建一个对象的数组
多维数组
- 相当于数组的数组
- 声明数组:int[][] MyArray2; 或者 int[][][] MyArray3;
分配内存空间,有两种方式
– 直接分配 int[][] MyArray2 = new int[2][3];
– 分别为为每一维分配 int[][] MyArray2 = new int[2][]; MyArray2[0]=new int[3];MyArray2[1]=new int[3];也可以创建时就赋初值
– int MyArray2[][]={{2,3},{1,5},{3,4}};
数组的拷贝
使用System.arraycopy()方法
Java方法
- 模块化(按功能)的程序设计—方法的调用
- 跟C语言的函数很类似,不同的是方法必须要给相应的类新建一个对象,通过对象来调用方法,并分配一定空间。
- 方法的调用过程
对象
- Everything is Object–万物皆为对象
- 所有事物都有两个方面
- 有什么(属性):用来描述对象
- 能够做什么(方法):告诉外界对象有哪些功能
类
- 一种抽象的数据类型
- 类是对象的抽象,用来描述某一类具有相同特性的对象
面向对象
- 符合人类看待事物的一般规律
- 对象的方法实现细节是屏蔽的,只有对象方法的是闲着了解细节。
- 注意区分一下三点
- 对象(本身)
- 对象的实现者
- 对象的调用者
- 对象之间的耦合性一定要低,例如主板和硬盘之间差别很大,高内聚,低耦合
面向过程VS面向对象
- 面向过程:算法+数据结构=程序
- 先有算法,后有数据结构,由过程、步骤、函数为中心。
- 面向对象:以对象为中心,先开发类,得到对象,通过对象之间相互通信实现功能。
- OOP关键:让每一个对象负责执行一组相关的任务
- 先有数据结构,然后再考虑算法。
public class Animal{
String name;//属性
int age; //属性
public Animal(String name,int age){ //构造方法:方法名与类名相同,没有返回值类型
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(name+" eating!!");
}
}
封装
- 把数据和行为结合在一个包中,并对对象的使用者隐藏数据的实现过程。
- 实例字段:对象中的数据成为对象的实例对象
- 方法:操作数据的函数和过程成为对象的方法
- 实现封装的关键:绝不让方法直接访问其他类的实例字段!
- this:指向当前类或对象
方法的参数传递
- 基本数据类型的参数按值传递
- 引用类型的参数按引用传递
方法的重载
- 方法名相同
- 参数类型和个数一定不同
- 返回值可以相同也可以不同
构造方法
- 主要功能:创建对象的时候初始化对象
- 每个类都会有
- 如果程序员定义类的时候没有定义构造方法的话,Java自动添加一个public的空构造方法
继承
- 是 is a 的关系
- 声明的形式
- public class Manager extends Employee{…}
- Java是单一继承语言
- 一个类只有一个直接父类,如果没有声明父类,则默认的父类为java.lang.Object
- 可以继承方法和属性,但不能继承构造方法,父类的构造方法是被子类的构造方法隐含的调用
- super关键字两种用法
- 代表指向父类的引用super.age或者是super.addAge()
- 代表调用父类的构造方法super();或者是super(“A”,”B”);
- instanceof运算符用来确定已经新建了的对象是用哪个类构造的。
多态
- 多态指的是编译时类型变化,而运行时类型不变,分两种
- 编译时多态:编译时动态重载
- 运行时多态:指一个对象可以具有多个类型,有三原则
– 对象不变
– 对象的调用只能限于编译时类型的方法,不能调用运行时类型方法,比如Animal a = new Dog(); 对象a的编译时类型为Animal,运行时类型为dog,注意编译时类型一定要为运行时类型的父类。
– 在程序运行时调用运行时类型,即它调用覆盖后的方法。
高级语言特性
static
- 静态变量或方法,一个类只有一份,被类的所有实例共享。
- 相当于所有用这个类定义的对象的所有空间里的全局变量。
- 定义后即可分配空间,不需要等生成实例就可以访问。
- 直接使用 类名.静态变量或方法名 来访问。
- 不能在static方法内部访问非static成员。
package sample;
public class Static Tese{
int x = 0;
public static void main(String[] args){
x = Algorithm.add(2,3);//会报错
System.out.println(x);
}
}
class Algorithm{ //原因是在一个非静态类里定义了一个静态方法,把这个类改成静态的就会消除错误
public static int add(int a, int b){
return a+b;
}
}
final
- 用来修饰一个类,方法,属性或者局部变量
- 不能被继承,不能被覆盖,不能被改变。
package sample;
public final calss FinalTest{
final int i = 10;
//构造函数
public FinalTest(){}
public final int getNumber(){
i= 20;//非法报错!final变量不能被覆盖(重新赋值)
return i;
}
}
class FinalSub extends FinalTest{}//非法报错!final类不能被继承
class FinalDemo{
final int getNumber(){return 0;}
}
class FinalDemoSub extends FinalDemo{
int getNumber(){return 20;}//非法报错!final变量的值不能被改变
}
abstract
- 用来修饰类,方法。
- 如果一个方法没有实现的代码,那么它必须被声明为抽象的方法
public abstract String getName();
- 如果一个类包含抽象方法,那它必须被声明为抽象类
public abstract class Account{
public abstract String getName();
}
- 抽象类不能实例化(不能生成对象),但可以定义一个抽象类的引用。
接口
- 接口是一种特殊的抽象类。
- 接口中所有的方法都是抽象方法。
- 一个类可以实现多个接口,接口中所有属性都会自动声明为final static
- 接口与接口之间可以多重继承。
访问权限控制
toString()
- 返回描述某个对象的字符串。
- 当直接用print等输出一个对象时,这个方法被隐含的调用。
- 一般来说我们会根据需要在自己写的类中覆盖这个方法,给出自己的描述形式。
class Account{
private String name;
private String balance;
public Account(String name,double balance){
this.name = name;
this.balance = balance;
}
public String toString(){
return "The account:"+name+" has balance:"+balance;
}
}
equals()
- equals(Object o)方法用来判断两个对象值是否相同,一般在定义类的时候被覆盖(改写)
- 和 == 不一样的是,==运算符是用来判断两个引用值是否相等(是否指向同一个对象)
args[]
- 用来存放传递给main()的参数。
wrapper
- 是Java的包装类
- 为什么会出现wrapper
- Java认为一切皆为对象,但是int、double等8种数据类型却不是对象,与Java的思想相矛盾
- 为了解决这个问题,出现了包装类,把基本数据类型进行包装,让它成为类
- 数据类型是数据类型,类是类
- Java不是100%面向对象,因为它有8个基本数据类型,是不能当成对象来看待的,只有它们的封装类,才是对象
- 封装类的一切方法的返回值和直接定义int类型的数据是一样的,这样,封装类就可以当做一个对象看待。
- 如果操作包装类,会涉及到封箱和拆箱等操作。
String和StringBuffer
- Java为了提高效率,为String类提供了字符串池
public class StringTest {
public static void main(String[] args) {
/* Java为String类提供了字符串池,
* 当我们重新生命一个String型变量为abc
* 将使用串池里原来的那个abc,不再重新分配内存
* 提高效率
*/
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);//结果是true
/* 如果使用普通的对象声明方式,即用new关键字
* 系统将会为str3和str4各分配一块内存
*/
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3 == str4);//结果是false
}
}
- StringBuffer内部实现的是字符数组,默认初始化大小为16.
StringBuffer sb = new StringBuffer();
sb.toString();//转化为String
sb.append("**");//追加字符串
- String类 vs StringBuffer类
- String类的实例一旦创建出来就不能再修改,各种貌似修改了的方法都是返回一个包含修改结果的新的String实例。
- 如果要频繁修改字符串或处理长字符串,那就用stringbuffer,更有效率。
测试例程
public class InterfaceTest {
public static void main(String[] args) {
Army a = new Army(3);
a.addWeapon(new Tank());
a.addWeapon(new Flighter());
a.addWeapon(new WarShip());
// a.addWeapon(new WarShip());
a.attacAll();
a.moveAll();
}
}
//定义一个接口Assaultable(可攻击的),该接口有一个抽象方法attack()。
interface Assaultable {
abstract public void attack();
}
//定义一个接口Mobile(可移动的),该接口有一个抽象方法move()
interface Mobile {
abstract public void move();
}
//定义一个抽象类Weapon,实现Assaultable接口和Mobile接口,但并没有给出具体的实现方法。
abstract class Weapon implements Assaultable, Mobile {
}
//定义3个类:Tank,Flighter,WarShip都继承自Weapon,分别用不同的方式实现Weapon类中的抽象方法。
class Tank extends Weapon {
public void attack() {
System.out.println("Tank attacks");
}
public void move() {
System.out.println("Tank moves");
}
}
class Flighter extends Weapon {
public void attack() {
System.out.println("Flighter attacks");
}
public void move() {
System.out.println("Flighter moves");
}
}
class WarShip extends Weapon {
public void attack() {
System.out.println("WarShip attacks");
}
public void move() {
System.out.println("WarShip moves");
}
}
//写一个类Army,代表一支军队
class Army {
private Weapon[] w = null;//用来存储该军队所拥有的所有武器
private int size = 0;
private Army() {
}
//在构造方法里通过传一个int类型的参数来限定该类所能拥有的最大武器数量
public Army(int i) {
w = new Weapon[i]; //用这一大小来初始化数组w
}
//把参数wa所代表的武器加入到数组w中
public void addWeapon(Weapon weapon) {
if (size >= w.length) {
System.out.println("军队装备足够了!");
return;
} else {
w[size] = weapon;
size++;
}
}
//w数组中的所有武器攻击
public void attacAll() {
for (Weapon wea : w) {
if (wea != null) {
wea.attack();
}
}
}
//w数组中的所有武器移动
public void moveAll() {
for (Weapon wea : w) {
if (wea != null) {
wea.move();
}
}
}
}
异常Exception
- java.lang.Exception类是Java中所有异常的直接或间接父类。即Exception类是所有异常的根类。
- 常见异常
- 算术异常:除数为0
- 空指针异常:某个引用为null,但却调用了它的某个方法,这时就会出现该异常
- 异常一般分为两大类
- Unchecked Exception(Runtime Exception):RuntimeException类是Exception类的子类,Java中的所有运行时异常都会直接或者间接地继承自RuntimeException类
- Checked Exception(非Runtime Exception):Java中凡是继承自Exception,而不继承自RuntimeException类的异常都是非运行时异常。
- 非运行时异常必须要处理,否则无法通过编译,两种方法
- 捕获异常:
public class ExceptionTest2
{
public void method() throws Exception { // 将异常抛出,由调用这个方法的方法去处理这个异常,如果main方法也将异常抛出,则交给Java虚拟机来处理
System.out.println("Hello World");
throw new Exception();// 抛出异常
}
public static void main(String[] args){
ExceptionTest2 test = new ExceptionTest2();
try{
test.method();
}
catch (Exception e){
e.printStackTrace();
}
finally{
System.out.println("Welcome");
}
}
}
- 将异常继续抛出:
public static void main(String[] args) throws Exception{ // main方法选择将异常继续抛出
ExceptionTest2 test = new ExceptionTest2();
test.method(); // main方法需要对异常进行处理
}
- 除数为0的异常处理栗子
public class ExceptionTest
{
public static void main(String[] args)
{
int c = 0;
try{ //可能发生异常的代码
int a = 3;
int b = 0;
// 这块代码出现了异常
c = a / b;
// 那么异常之后的代码都不会被执行
System.out.println("Hello World");
}
catch (ArithmeticException e){ // 异常处理代码
e.printStackTrace();
}
finally{
//不管有没有发生异常,finally语句块都会被执行
System.out.println("Welcome");
}
System.out.println(c);
// 当b为0时,有异常,输出为c的初始值0
}
}
- 一个try后面可以跟多个catch,但不管多少个,最多只会有一个catch块被执行。
- try块中有return语句时,仍然会首先执行finally块中的语句,然后方法再返回。