Java学习笔记
本笔记是在看浙大翁恺老师的视频教学时所做,希望对Java初学者有帮助!
一、Java基础
1、正确认识Java
(1)Java是一种有生产力的OOP语言,C++能做的Java都能做
(2)Java与网络关系不大,更不是用来做网页的
(3)Java是UNIX世界的产物,具有UNIX的思想
(4)Java在国外广泛的被用来做各种应用
2、Java历史
(1)Brithday:May 23,1995
(2)1991:Set-Top box:Jame Gosling
(3)1994:OAK and FirstPerson
(4)1995:Java and HotJava-Internet play
3、Java环境
编译 执行
Java源程序------>字节码文件----->Java虚拟机---->Linux、Windows、Mac
4、Java平台
(1)The Java Virtual Machine(Java VM)
(2)The Java Application Programming Interface(Java API)
5、Java特点
(1)Cross Platform/Portable
Portable:the dream from UNIX and C to Java
1)JVM
2)Unique data type
Int:32-bit
Char:16-bit,Unicode
(2)Capacity:high or low?
Low:
1)Interpreted
2)Code check
3)Stack machine
High
1)JIT
2)Mutil-thread
3)Byte code simple design
(3)Stable and secure
1)No point
2)Index check
3)Auto memory management
(4)Simple:KISS
1)C++ like
2)No point
3)Auto memory check
(5)Pure OOP
Java = C++ --
1)Mutil-inheritance
2)Virtual inheritance
3)Template
4)Operator overloading
(6)Dynamic
1)Java没有传统的程序的概念
2)Java认为全世界的类和对象是一个空间
3)Java你写的程序的编译结果是这个空间的一部分
4)Java所谓的运行程序就是从空间中某类的某个特殊的方法开式启动
(7)Storage of objects
1)For C,efficiency is the most important,so programmers can make decision by their own.
2)For Java,all objects should be constructed in runtime and be stored in heap.
(8)Create and destroy objects
1)You must create your objects
2)But can not destroy them by yourself
3)There is a recycle mechanism to help clean up objects that will never be used again.
(9)Container
Is an object to hold other objects
1)vector
2)stack
3)queue
(10)Root
1)Every class in Java is a descendant of one class:Object
2)So all objects in Java is objects of the class Object.
3)In this way,container is an object that can hold objects.
(11)handle
1)You can not hold the object itself,instead,you can have a handle that refer to it.
String s;
2)Here s is only a handle that refer to nothing.
(12)new
String s = new String(\"a String\");
1)An object of String is created
2)The object is initialized w/\"a string\"
3)A variable as handle to String is created
4)The value of the handle variable is assign to the object
(13)Primitive types
boolean 1-bit true false
char 16-bit Unicode
byte 8-bit -127~128
short 16-bit -32767~32768
int 32-bit
long 64-bit
float 32-bit
double 32-bit
(14)First Java Program
class HelloWorld
{
public static void main(String [] args)
{
System.out.print(\"Hello World!\");
}
}
二、深入学习Java
1、建立新的数据类型:class
class ATypeName{
/*class body goes here */
}
2、方法、参数和返回值
return Type methodName(/*argument list*/)
{
/*Method body*/
}
Java中的方法只能作为类的一部分创建
3、赋值
1)当\"from one object to another\"赋值,实际上是将句柄从一个地方赋值到另一个地方
-Case:Assignment.java
//:Assignment.java
//Assignment with objects is a bit tricky
class Number {
int i;
}
public class Assignment {
public static void main(String [] args){
Number n1 = new Number();
Number n2 = new Number();
n1.i = 9;
n2.i = 47;
System.out.println(\"1: n1.i: \" + n1.i + \", n2.i: \" + n2.i);
n1 = n2;
System.out.println(\"2: n1.i: \" + n1.i + \", n2.i: \" + n2.i);
n1.i = 27;
System.out.println(\"3: n1.i: \" + n1.i + \", n2.i: \" + n2.i);
}
}
2)将一个对象传递到方法内部时,也是赋值
-Case:PassObject.java
//:PassObject.java
//Passing objects to methods can be a bit tricky
class Letter{
char c;
}
public class PassObject {
static void f(Letter y){
y.c = \'z\';
}
public static void main(String [] args) {
Letter x = new Letter();
x.c = \'a\';
System.out.println(\"1: x.c: \" + x.c);
f(x);
System.out.println(\"2: x.c: \" + x.c);
}
}
4、关系运算符
关系运算符==和!=页能对任何对象进行,但是它们的含义常常使人迷惑
-Case:Equivalence.java
//:Equivalence.java
public class Equivalence {
public static void main(String [] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}
5、String运算符+
+运算符可以用来连接字符串
int x = 0, y = 1, z = 2;
String sString = \"x, y, z\";
System.out.println(sString + x + y + z);
System.out.println(y + z + sString);
6、Break和continue
1)A plain continue goes to the top of the innermost loop and continues.
2)A labeled continue goes to the label and re-enters the loop right after that label.
3)A break \"drops out of the bottom\" of the loop.
4)A labeled break drops out of the bottom of the end of the loop denoted by the label.
-Case:LabeledFor.java
//:LabeledFor.java
//Java \"labeled for loop\"
public class LabeledFor {
public static void main(String [] args) {
int i = 0;
outer: //Can\'t have statements here
for (; true; ) { //infinite loop
inner: //Can\'t have statements here
for (; i < 10; i++) {
prt(\"i = \" + i);
if (i == 2) {
prt(\"continue\");
continue;
}
if (i == 3) {
prt(\"break\");
i++; //Otherwise i never
//gets incremented
}
if (i == 7) {
prt(\"continue outer\");
i++; //Ohterwise i never
//gets incremented
continue outer;
}
if (i == 8) {
prt(\"break outer\");
break outer;
}
for (int k = 0; k < 5; k++) {
prt(\"k = \" + k);
if (k == 2) {
prt(\"continue\");
continue;
}
if (k == 4) {
prt(\"break inner\");
k++; //Otherwise k never
//gets incremented
continue inner;
}
}
}
}
}
static void prt(String s)
{
System.out.println(s);
}
}
7、初始化和清除
As the computer revolutiion progresses, \"unsafe\" programming has become one of the major culprits that makes programming expensive.
1)初始化和清除事程序设计安全性的两个最重要的问题
2)C++为我们引入了构造函数的概念,Java也沿用了这个概念,但新增了自己的垃圾收集器
8、用构造函数自动初始化
如果某个类有一个构造函数,那么在创建对象的时候,Java会自动调用那个构造函数,构造函数的名字和类的名字相同
-Case:SimpleConstructor.java
//: SimpleConstructor.java
// Demonstration of a simple constructor
class Rock {
Rock() {//This is the constructor
System.out.println(\"Creating Rock\");
}
}
public class SimpleConstructor {
public static void main(String [] args) {
for (int i = 0; i < 10; i++)
new Rock();
}
}
9、Methods overloading
One of the important features in any programming language is the use of names.
我们用名字引用或描述所有对象与方法。在日常生活中,我们用相同的词表达多种不同的含义,即词的“重载”
大多数程序设计语言要求我们为每个函数都设定一个独一无二的标识符。但是构造函数的出现要求函数名也能够“重载”
Often,the same word expresses a number of different meanings -- it\'s overloaded.
-Case:Overloading.java
//: Overloading.java
// Demonstration of both constructor and ordinary method overloading
import java.util.*;
class Tree {
int height;
Tree() {
prt(\"Planting a seedling\");
height = 0;
}
Tree(int i) {
prt(\"Creating new Tree that is \" + i + \" feet tall\");
height = i;
}
void info() {
prt(\"Tree is \" + height + \" feet tall\");
}
void info(String s) {
prt(s + \": Tree is \" + height + \" feet tall\");
}
static void prt(String s) {
System.out.println(s);
}
}
public class Overloading {
public static void main(String [] args) {
for(int i = 0; i < 5; i++) {
Tree t = new Tree(i);
t.info();
t.info(\"overloaded method\");
}
//Overloaded constructor:
new Tree();
}
}
10、区分重载方法
1)每个重载的方法都必须采取独一无二的自变量类型列表
2)返回类型重载??
11、缺省构造函数
1)如果一个类没有定义构造函数,则编译程序会帮我们自动创建一个缺省构造函数
2)然而一旦定义了一个构造函数,就不会帮我们自动生成一个
12、this
1)this关键字可以为已调用了其方法的那个对象生成相应的句柄
-Case:Leaf.java
//:Leaf.java
//Simple use of the \"this\" keyword
public class Leaf {
private int i = 0;
Leaf increment() {
i++;
return this;
}
void print() {
System.out.println(\"i = \" + i);
}
public static void main(String [] args) {
Leaf x = new Leaf();
x.increment().increment().increment().print();
}
}
2)在一个构造函数中调用另一个构造函数时,用this关键字
-Case:Flower.java
//: Flower.java
//Calling constructors with \"this\"
public class Flower{
private int petalCount = 0;
private String s = new String(\"null\");
Flower(int petals) {
petalCount = petals;
System.out.println(\"Constructor w/ int arg only, pet\" + petalCount);
}
Flower(String ss) {
System.out.println(\"constructor w/ String arg only, pet\");
s = ss;
}
Flower(String s, int petals) {
this(petals);
//! this(s); //Can\'t call two!
this.s = s; //Another use of \"this\"
System.out.println(\"String & int args\");
}
}
构造函数调用必须是构造函数的第一条语句,并且不能在一个构造函数调用两个以上的构造函数
13、清除:收尾和垃圾收集
1)垃圾收集机制只知道怎样释放由new分配的内存,所有它不知道如何释放对象的“特殊”内存。一旦垃圾收集机制准备好释放对象占用的存储空间,它首先调用finalize()。
2)但是finalize()和C++的系构函数截然不同
垃圾收集不等于析构
对象可能不会被当做垃圾被收集掉
垃圾收集只跟内存有关
14、成员初始化
Java goes out of its way to guarantee that any variable is properly initialized before it is used.
由于任何方法都可以初始化或使用那个数据,所以在正式使用数据前,若还有强迫程序员将其一一初始化成一个适当的值,就可能不够实际。因此,一个类的所有primitive数据成员都会保证获得一个缺省值。当然,句柄会获得null值。
15、定义初始化
一个直接的做法是在定义数据成员的同时也为其赋值
class Measurement {
boolean b = true;
char c = \'x\';
int i = 47;
}
也可以用相同的方法初始化对象
class Measurement {
Depth o = new Depth();
}
16、可以调用一个方法进行初始化
clas Clnit {
int i = f();//...
}
当然这个方法也可以使用参数
class Clnit {
int i = f(); int k = g(i); //...
}
但是那些参数不能是尚未初始化的其它数据成员
class ClnitWrong {
int j = g(i); int i = f(); //...
}
17、初始化顺序
在一个类里,初始化的顺序是由变量在类内的定义顺序决定的。即使变量定义大量遍布于方法定义的中间,那些变量仍然会在调用任何方法只前得到初始化--当然在构造函数之前
-Case: OrderOfInitialization.java
//: OrderOfInitialization.java
// Demonstrates initialization order.
// When the constructor is called, to create a Tag object, you\'ll see a message:
class Tag {
Tag(int marker) {
System.out.println(\"Tag(\" + marker + \")\");
}
}
class Card {
Tag t1 = new Tag(1); // Before constructor
Card() {
//Indicate we\'re in the constructor:
System.out.println(\"Card()\");
t3 = new Tag(33); //Re-initialize t3
}
Tag t2 = new Tag(2); //After constructor
void f() {
System.out.println(\"f()\");
}
Tag t3 = new Tag(3); //At end
}
18、静态数据初始化
1)静态的东西属于类
2)类Class与类对象
3)静态数据成员是在这个类的第一个对象要创建的时候初始化
-Case:StaticInitialization.java
//:StaticInitialization.java
// Specifying initial values in a class definition
class Bowl {
bowl(int marker) {
System.out.println(\"Bowl(\" + marker + \")\");
}
void f(int marker) {
System.out.println(\"f(\" + marker + \")\");
}
}
class Table {
static Bowl b1 = new bowl(1);
Table() {
System.out.println(\"Table()\");
b2.f(1);
}
void f2(int marker) {
System.out.println(\"f2(\" + marker + \")\");
}
static Bowl b2 = new Bowl(2);
}
class Cupboard {
Bowl b3 = new Bowl(3);
static Bowl b4 = new Bowl(4);
Cupboard() {
System.out.println(\"Cupboard()\");
b4.f(2);
}
void f3(int marker) {
System.out.println(\"f3(\" + marker + \")\");
}
static Bowl b5 = new Bowl(5);
}
public clas StaticInitialization {
public static void main(String [] args) {
System.out.println(\"Creating new Cupboard() in main\");
new Cupboard();
System.out.println(\"Creating new Cupboard() in main\"):
new Cupboard();
t2.f2(1);
t3.f3(1);
}
static Table t2 = new Table();
static Cupboard t3 = new Cupboard();
}
19、初始化顺序
1)类型为Dog的一个对象首次创建时,或者Dog类的静态方法/数据首次访问时,Java解释器必须找到Dog.class
2)找到Dog.class后,它的所有的静态初始化模块都会运行。因此,静态初始化仅发生一次
3)创建一个new Dog()时,new语句首先会在堆里分配一个足够的空间
4)这个空间将会被清除为零,因此Dog中所有的数据成员都得到了缺省值
5)执行定义初始化
6)执行构造函数
20、显式初始化
1)Java允许我们将其它静态初始化工作划分到类内一个特殊的“静态构造从句”(又叫“静态块”)里
-Case:ExplicitStatic.java
//:ExplicitStatic.java
// Explicit static initialization with the \"static\" clause.
class Cup {
Cup(int marker) {
System.out.println(\"Cup(\" + marker + \")\");
}
void f(int marker) {
System.out.println(\"f(\" + marker + \")\");
}
}
class Cups {
static Cup c1;
static Cup c2;
static {
c1 = new Cup(1);
c2 = new Cup(2);
}
Cups() {
System.out.println(\"Cups()\");
}
}
2)Java 1.1可以用类似的方法初始化非静态数据成员
-Case:Mugs.java
//: Mugs.java
// Java 1.1 \"Instance Initialization\"
class Mug {
Mug(int marker) {
System.out.println(\"Mug(\" + marker + \")\");
}
void f(int marker) {
System.out.println(\"f(\" + marker + \")\");
}
}
public class Mugs {
Mug c1;
Mug c2;
{
c1 = new Mug(1);
c2 = new Mug(2);
System.out.println(\"c1 & c2 initialized\");
}
Mugs() {
}
}
21、数组
1)数组代表一系列对象或者基本数据类型的对象都封装在一起--采用一个统一的标识符名称
2)数组的定义和使用是通过索引运算符进行的
int[] a; int a[];
3)Java不允许我们在数组定义时指定一个数组有多大
4)数组变量实际上是一个指向数组的句柄
-Case:Arrays.java
//:Arrays.java
// Arrays of primitives.
public class Arrays {
public static void main(String[] args) {
int[] a1 = {1, 2, 3, 4, 5};
int[] a2;
a2 = a1;
for(int i = 0; i < a2.length; i++)
a2[i]++;
for(int i = 0; i < a1.length; i++)
prt(\"a1[\" + i + \"] = \" + a1[i]);
}
static void prt(String s) {
System.out.println(s);
}
}
22、对象数组
1)对于对象数组,数组的成员实际上是句柄
-Case:ArrayClassObj.java
//:ArrayClassObj.java
//Creating an array of non-primitive objects.
import java.util.*;
public class ArrayClassObj {
static Random rand = new Random();
static int pRand(int mod) {
return Math.abs(rand.nextInt()) % mod;
}
public static void main(String[] args) {
Integer[] a = new Integer[pRand(20)];
prt(\"length of a = \" + a.length);
for(int i = 0; i < a.length; i++) {
a[i] = new Integer(pRand(500));
prt(\"a[\" + i + \"] = \" + a[i]);
}
}
static void prt(String s) {
System.out.println(s);
}
}
2)对象数组也可以定义初始化
-Case:ArrayInit.java
-Case:VarArgs.java
23、隐藏实施过程--访问控制
A primary consideration in object-orieented design is \"separation the things that change from the things that stay the same.\"
1)每个库的用户(client programmer)必须能依赖自己使用的库,并知道一旦新版本的库推出,自己不需要改写代码
2)库创建者应声明哪些是客户程序员可以使用的,哪些是不可以使用的
24、包:库单元
1)用import来引用包或包里的成员
import java.util.*;
import java.util.Vector;
2)之所以要这样的引入,是为了提供一种特殊的机制,来实现命名空间的管理
25、编译单元
1)每个编译单元必须是以.java结尾的文件名称,在一个编译单元里,可以有一个public的类,这个类的名字必须与文件的名字相同,在一个单元内,只能有一个public的类
2)编译一个.java文件时,对应于文件中的每一个类,会得到一个.class文件,文件名和类名字相同。一个程序是一堆.class文件
26、定义包
1)一个库是一堆这样的.class文件。它们被定义为一个包,但是并不真正的合并在一个文件中
package mypackage;
public class MyClass;
2)现在,如果客户程序员想要使用MyClass,就要用import来引入mypackage包,或者是使用MyClass的全名
import mypackage;
MyClass m = new MyClass();
mypackage.MyClass m = new mypackage.MyClass();
27、CLASSPATH
1)将某个特定包使用的所有.class文件都放在一个目录下
2)CLASSPATH包含一个或多个目录,它们作为一种特殊的根使用,从这里展开对.class文件的搜索
-自动编译
-冲突
-Classpath的陷阱
-用import来改变行为
28、类成员的访问属性
针对类内的每个成员的每个定义,Java访问属性public,protected和private都放在它们的前面--无论是数据成员还是方法
-“Friendly”(缺省包)
-public:界面访问(accessor/mutator)
-private:不能接触!
-protected:“某种友好”
29、类的访问控制
1)一个编译单元(文件)中只能有一个public的类。因此一个编译单元只有一个唯一的公共界面,其余的类都是“friendly”的。public类的名字必须和文件的名字一样
2)可以,尽管很少见,一个编译单元没有一个public类,所有的类都是“friendly”的,那么文件名可以任意起
-Case:Lunch.java
//: Lunch.java
//Demonstrates class access specifiers.
//Make a class effectively private with private constructors:
class Soup {
private Soup() {}
// (1)Allow creation via static method:
public static Soup makeSoup() {
return new Soup();
}
// (2)Create a static object and return a reference upon request.
// (The \"Singleton\" pattern):
}