1、Knuth:算法+数据结构 = 程序,算法优先。
面向对象:数据优先。面向对象利于划分,隔离子模块,方便调试与开发。
2、类(class)是构造对象的模板。类->对象的过程叫做实例化(instance)。
3、对象一般将数据域(instance fields)封装(encapsulation)在对象内部,对外提供方法(method),用于整体操纵类的状态。
4、OOP原则一:封装是必须的,不能让外部直接操纵类内部数据对象。
5、OOP原则二:类可以扩展自另外一个类,称为继承(inheritance)。
6、OOP对象三特性:行为(method)、状态(内部state,fields)、标识(如何区分两个对象,如订单ID、学号等)
7、类之间的关系:
依赖( use-a ):Order需要使用Account的用户配送地址
聚合( has-a ):Order中包含若干个Item
继承 ( is-a ):DiscountOrder继承自Order,实现了一个打折策略
8、并不是所有类都具有面向对象特征,例如Math类的各个方法Math.sin()/Math.pow(),方法不会改变内部状态,因为这个类就没有内部状态的域fields。这种类也是允许的。
9、类(class)的构造函数(construct)负责构造、初始化对象(object)。
10、Date dt = new Date();
dt仅仅是一个Date对象的引用。
如果把dt赋值给另外一个Date变量dt1,则他们都指向的dt。
import java.util.Date; public class Test { public static void main(String [] args) { Date dt = new Date(); Date dt2 = dt; System.out.format("Is dt and dt2 the same object, %b\n",(dt==dt2)); } }
11、Java中,对象引用默认为null,避免了C++中未初始化的指针未初始化则未随机值导致的各种内存错误。
12、GregorianCalendar继承自Calendar,提供了阳历相关的各种接口。
构造函数,可以指定当前时间或者指定时间
//Now GregorianCalendar cal2 = new GregorianCalendar(); //Spcific the date: dooms day GregorianCalendar cal = new GregorianCalendar(2012, Calendar.DECEMBER, 23, 0, 0);
访问器(Accessor):可以获取日历的某个域:年、月、日、小时。。。
//Show Month,注意月份是从0开始的,比如12月会输出11! System.out.println(cal.get(Calendar.MONTH)); //获取当地时区一周的第一天是周几,例如中国就是返回1。 System.out.println(cal.getFirstDayOfWeek());
修改器(Mutator method):
cal.add() // 增加天、月等 cal.set(xxx) // 直接设置月、天等
在Calendar和Date之间转换:
Date dt = cal.getTime();
13、类java.text.DateFormatSymbols用于日期的格式化,可输出Locales所在地字符串的年、月、日。。周一。。。周日。。。
//Print 周一 ... 周日 for(String s:new DateFormatSymbols().getWeekdays()) { System.out.println(s); }
14、自定义类推荐的格式:
class XX { constructor1()... constructor2()... method1() method2() field1 field2 }
15、如果类XXXTest.java引用了XXX.java,则javac XXXTest.java时候,会自动编译XXX.java
16、public:所有类都可以访问、private:只有类内部才能访问。
17、构造函数与类同名、有0+个参数、无返回值、new后触发。
18、类内部可用this指明自己,在参数与内部域同名的时候,经常实用。
19、公有的域更改器、域访问器,私有的域。
20、不要直接返回引用对象!这将破坏函数的封装性!
//不要直接返回对象,很危险!! public Date getHireDay() { return this.hireDay; } //访问之前 System.out.println("name:"+e2.getName()+",salary:"+e2.getSalary()+",hire:"+e2.getHireDay()); //e2.getHireDay()之后会修改e2内部的hireDay对象! e2.getHireDay().setTime(0); //被修改了 System.out.println("name:"+e2.getName()+",salary:"+e2.getSalary()+",hire:"+e2.getHireDay());
上面的代码中,返回的Date对象可以被任意修改(因为Java中没有C++那种拷贝函数,每个对象都是引用)。
正确的做法是:在返回之前,先克隆!(拷贝出来一个完全新的对象!)
//正确的做法 public Date getHireDay() { return (Date)this.hireDay.clone(); }
当然,这个前提是,你要纯粹的get方法,不希望别人修改。
21、一个类可以访问所有该类的对象!即同类访问对象,不受private限制。
这个在实现equals方法时候非常有用:
class Employee { bool equals(Employee other) { return this.name.equals(other.name); } .... private String name; }
22、如果一个公有方法需要由多个步骤实现(例如基于TCP的App协议)。那么应该把这些子步骤的方法设置为私有的。
23、final可用于修饰对象的实例域。
private String name; //用于基本类型,一旦name创建后就无法被修改了。
private Date day; //用于非基本类型(对象类型),该引用不会变,但类内部的域是可以变的。
24、如果数据域定义为static,则这个类的所有对象将共享这个数据域。
class XXX { public XXX() { nextID++; this.id = nextID; } private static int nextID = -1; private int id; }
如上的nextID,为类所有对象共享,递增的ID,没创建一个类时。
25、如果定义为public static final,则这个变量可以被其他类不构造改类对象,就直接实用。经常用于常量。
class Math { public static final double PIE = 3.1415926; }
也可以用于共享的资源,例如非常熟悉的System.out:
public class System { public static final PrintStream out=...; }
26、static用于方法上,成为静态方法。静态方法内部无法使用this。因此,静态方法不能操纵对象内的实例域。但可以操纵类静态域(static域).
27、静态方法应用的场景
(1)所需要的所有参数都通过参数显示提供了如Math.pow()。
(2)一个方法只需要访问类的静态域名。
28、回顾下C语言中的static意义
(1)函数内部的static变量,再次进入时不会被初始化。
(2)用于多文件,变量共享。
而C++又给static重行下了定义:
(1)类的静态(static)数据域,被所有该类的对象共享且只有一个。
C++的static意义和Java是一致的。不过C++用::访问,Java统一都用.访问。
29、工厂方法(Factory):
NumberFormat currencyFomartter = NumberFactory.getCurrencyInstance();
NumberFormat precentFomartter = NumberFactory.getPrecentInstance();
使用工厂方法的原因是:同一个构造函数,无法返回两个不同的子类,例如上面代码中:
30、main方法:虽然写在类中,但不合任何类绑定,也无法访问类的静态域。
public static void main()
31、每个类都可以有自己的main方法,但具体执行哪个main,取决于
java xxx 运行的是哪个类。
32、Java的参数调用总是传值,方法得到的所有参数都是参数值的一个拷贝,这个有点复杂:
(1)基本数据类型,int、double这种,在函数里的更改不会影响调用者。
(2)对象:传值传的是引用,这样依赖,在参数里面改变对象,会影响调用它传入的对象状态。
(3)对于String:函数里面对String参数的更改不会影响外面。这也是容易理解的。因为String指向的字符串是共享的,没有一定的对象。到了外面就被抛弃了,下面的代码将输出两次”aaa“,即没有成功更改String a。
public class Test { public void TestString(String a) { a = "aaa_aaa"; } public static void main(String [] args) { Test t = new Test(); String a = "aaa"; System.out.println(a); t.TestString(a); System.out.println(a); } }
33、重载(overload):多个方法有相同的名字、不同的参数。但不允许有仅返回类型不同的函数。
34、如果在构造函数中没有给域赋值,则会被默认初始化为:0、False或者null。
35、如果没有在类中写构造函数,Java会提供默认的构造函数,将所有域按上面的0、false、null初始化。
36、可以不用构造函数,在类中显示对域初始化,如下:
class Emplyoee { private String name="xxx"; }
甚至可以不一定是常量初始化,可以用函数:
class Emplyoee { static int assignID() { return id++; } private String name=assignID(); }
37、尽量不要让函数的参数名和对象内的域名相同,以防隐藏起来。或者显示的指定this,例如:
class XXX { public func(String name) { this.name = name; } }
38、可以从一个构造函数中调用另外一个构造函数:将this(xxx.xxx)放在构造函数的第一位,如下:
public Employee { public Employee(double s) { this("name", s); //......做其他事情 } }
39、Java还有初始化块机制,在类中匿名的包含块,只要对象被构造,这些块一定会被执行。这种方法不是必须的,一般可以通过其他构造方法替换掉。
public class Employee { ..... public Employee() { } //Init block { name = "aaa"; salary = 10.0; } private String name; private double salary; }
40、静态初始化块可以对static域初始化,第一次调用类的时候,static块执行。(放load Configure不错!)
public class Employee { ..... public Employee() { } //Static Init block static { id = 0; } static private int id; }
41、java.util.Random对象,产生随机值。
int nextInt(int n) // 产生0~n-1 之间的随机数。
42、Java不需要析构函数(因为对象垃圾回收,自动释放)。如果用JNI调用了其他资源,或者数据库连接、文件句柄等。可以添加finalize方法,它在对象被回收前一定会被调用一次。建议:对于这些资源的释放,人工加一个close方法,确保人工关闭!
43、Java使用包(package)将类组织起来。
44、导入类有两种方法:
1、全路径写明
2、import
两种方法如下:
//全写,很讨厌 java.util.Date d = new java.util.Date(); //import import java.util.Date; //Another import import java.util.*;
import要注意不要产生冲突,比如java.util.Date和java.sql.Date,此时,就必须写全路径了。
45、import时候,也会自动带入静态函数、常量。所以import java.lang.Math之后,就可以直接pow()了,不用再加Math了。
46、将类放在别的包下,需要在文件头部声明package:
package com.coder4.TestClass public class TestClass { ...... }
但是编译、运行的时候,有点不太一样:
#编译,用目录 javac com/coder4/TestClass.java #执行,用包.名 java com.coder4.TestClass
47、如果函数、域没有写明public、private,则默认是包可用的,即这个包中其他类都可以访问、修改它。
class XXX { //everyone in same pakcage can modifiy me String str; }
48、可以把一堆类打成jar包,方便运行、安装。注意jar包依赖的其他class文件,一定要在path变量下。否则,就得用java -classpath xxx 指定了。
49、JDK文档注释:javadoc,写符合它的注释,将来可以生成HTML样子的文档!
50、javadoc: /**开始 */结束
51、javadoc类注释:
/** * JavadocDemo.java,一个显示JavaDoc注释的Applet * <p>注意这只是HelloApplet的一个带注释的版本</p> * @see java.applet.Applet * @see javax.swing.Japplet */ public class JavadocDemo extends Applet{
52、方法注释
/** * A method * @param a a is xxxx * @param b b is xxxx * @return xxxxx */ public String method(int a, int b)
53、域注释(成员变量)
/** * The "HEARTS" var */ public static final int HEARTS = 1;
54、其他注释:
@author 作者
@version 版本
@since 自xx版本
@desprecated text 废弃
@see xxx
@see 的xxx又三种情况
(1)@see com.xx.xxClass#Method -> 直接引用其他类的方法
(2)@see <a href="http://www.coder4.com" >链接</a> -> 指向链接
(3)@see "Text" -> 纯指向文本
55、包注释:方法一:package.html命名的页面。方法二:package-info.Java的文件,用javadoc注释。
56、从注释生成javadoc网页。
javadoc -d docDir *.java
57、类设计技巧:
(1)数据域一定要私有
(2)一定要对局部数据初始化
(3)不要在类中使用过多的基本数据类型(比如User包含street、city、postcode,不如让他包含一个Address,后者再包含street、city等细碎的信息)
(4)不是所有类都要getter和setter,如果不要更改状态的,就不要加上。
(5)类名、方法要体现出用途
(6)功能过大的类要拆分、但也不可拆分太细!
Muchas gracias. ?Como puedo iniciar sesion?