目录
软件方法
课程要求
学习面向对象这种软件开发方法(目前概念越来越广),通过java来了解面向对象的编程具体怎么实现。
随记
- 类,对象:
- 对象是类的一个实例
- c语言可以构建面向对象所有的结构
- 类集合了属性和方法
- 面向对象的三大特征:
- 封装(encapsulation):
- private, protected, public
- 可作用于属性和方法,一般构造方法和成员方法都是public, 属性都是private
- 一般是隐藏对象的属性和实现细节,但是提供方法的接口
- 提供公开的方法
- 提高了软件开发的效率
- 继承(inheritance):
- 子类与父类
- 子类自动具有父类属性和方法,添加自己特有的属性和方法,并且子类使用父类的方法也可以覆盖/重写父类方法
- 可以实现代码的复用(当然功能不止于此)
- 多态(polymorphism):
- 父类有多个子类
- 子类覆盖/重写父类方法
- 相当于是根据实际创建的对象类型动态决定使用哪个方法
- 所有的子类都可以看成父类的类型,运行时,系统会自动调用各种子类的方法
- UML可以画出类之间的关系
- java程序设计
- 百分百面向对象
- 不存在类以外代码
- 只能采用面向对象方法编程
- java文件命名规范
- 必须以.java结尾
- 源文件中如果只有一个类,文件类必须与该类名相同
- 如果有多个类,且没有public类,文件名可与任一类名相同
- 有多个类,且有public类,文件名必须与该类名相同
- 一个JAVA源文件只能有一个public类,一个文件中只能有一个main主函数
- 静态方法/static,可以直接用类和函数名直接调用,和普通方法的区别是不用new一个示例
- static 方法可以直接调用,abstract方法存在的类肯定是抽象类
- 抽象方法不定义具体内容
- 多态的实现,先定义抽象的(abstract)父类,然后子类继承父类然后定义父类的抽象方法
- 通过抽象方法固定通用接口
- 子类通过强制实现抽象方法实现多态
- 抽象父类可以定义属性和构造函数
- 抽象父类不能实例化,只能通过向上转型的方法定义
- 抽象父类可以向下转型成子类
- 父类的方法一般是抽象方法,不定义具体内容,留给子类定义,父类出现的抽象方法子类必须全部定义
- 多态的主要特点就是父类的方法全部是抽象的
- 多态例子
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a; // 向下转型
c.work();
}
else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
PPT整理
1. 对象,类
- 使用对象之前要先声明和创建
- 类定义了对象的类型,所有对象都是类的实例,所有的类描述了属性和定义了方法
2.面向对象
- 面向对象的编程有4个特点
- 封装:保护类的属性和方法, 类里面的属性的数据是private的, public的方法定义了对象的接口。权限修饰符: private, default, protected, public。
- 继承:B继承A,重用,修改,添加,A所有的属性都存在于B中,A的方法可以在B中重新定义,B方法的改动不会影响A
- 多态:一个对象属于多个类,通过使用不同类中的方法属于不同的类,父类是抽象类,各个子类继承父类并定义方法,调用的时候根据不同子类调用方法。判断类型是否相同instanceof,声明的时候可以这么声明: A a = new B(),其中B是A的子类, 这种声明方法叫做向上转型。向下转型: B b = (B) a
- 动态链接: 通过PPT上的例子,我感觉和继承很像,这部分需要更深入了解才能明白。
3.JAVA
- 数据类型: int, float, double, char, string, boolean, byte, long, short, JAVA里面也有这些数据类型的类:
其中Characte应该为Character
还有异常的抛出throws
try-catch-finally
try
{
// 可能会发生异常的程序代码
}
catch (Type1 id1)
{
// 捕获并处置try抛出的异常类型Type1
}
catch (Type2 id2)
{
//捕获并处置try抛出的异常类型Type2
}
finally
{
// 无论是否发生异常,都将执行的语句块
}
自定义异常:
class NombreNegatifException extends Exception
{
public NombreNegatifException()
{
System.out.println("Vous avez un nombre négatif !");
}
}
在类的方法中抛出新的异常:
public int Count() throws Exception{
if (...){
throw new Exception("...");
}
}
类FileReader,FileWriter,使用里面的方法read()和write(x)和close()
比如:
public enum Jour
{
LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE;
}
class EssaiJour
{
public static void main(String[] args)
{
Jour jour = Jour.valueOf(args[0]);
if (jour == Jour.SAMEDI) System.out.print("fin de semaine : ");
switch(jour)
{
case SAMEDI :
case DIMANCHE :
System.out.println("se reposer");
break;
default :
System.out.println("travailler");
break;
}
}
}
举例:
class Main
{
@FunctionalInterface
public interface maFonction
{
Integer appliquer(Integer p);
}
public static Vector<Integer> transforme(Vector<Integer> v, maFonction function)
{
Vector<Integer> nouveauVect = new Vector<Integer>();
for (int i = 0; i < 3; i++)
{
nouveauVect.add(function.appliquer(v.get(i)));
}
nouveauVect.add(v.get(3));
return nouveauVect;
}
public static void main(String[] args)
{
Vector<Integer> vi = new Vector<Integer>(4);
vi.add(1); vi.add(4); vi.add(83); vi.add(18);
System.out.println("Les valeurs du vecteur initial : ");
System.out.print(vi.get(0)+" "); System.out.print(vi.get(1)+" ");
System.out.print(vi.get(2)+" "); System.out.println(vi.get(3));
vi = transforme(vi,s -> (s * 2));
System.out.println("Les valeurs du vecteur modifié : ");
Iterator iter = vi.iterator();
while (iter.hasNext())
{
System.out.print(iter.next() + "");
}
System.out.println();
}
}
4.数据结构
- 数据结构一般含有以下功能:创建,插入,寻找,删除,排序
- 二维数组,举例说明:
String tab[][]={ {"a", "e", "i", "o", "u"}, {"1", "2", "3", "4"} };
int i = 0, j = 0;
for(String sousTab[] : tab)
{
j = 0;
for(String str : sousTab)
{
System.out.println("Valeur du tableau à l'indice ["+i+"]["+j+"]: " + tab[i][j]);
j++;
}
i++;
}
声明数组:数组类型加变量名
或者
int tabEntiers[];
tabEntiers = new int[40];
// création effective du tableau précédent
- 列表,包含ArrayList, LinkedList
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList优于LinkedList,因为ArrayList可以随机定位,而LinkedList要移动指针一步一步的移动到节点处。(参考数组与链表来思考)。对于新增和删除操作add和remove,LinedList比较占优势,只需要对指针进行修改即可,而ArrayList要移动数据来填补被删除的对象的空间。
public class Liste<T>
{
protected T valeur;
protected Liste<T> succ;
protected Liste<T> pred;
public T valeur()
{
return valeur;
}
public void changerValeur(T x)
{
valeur = x;
}
public Liste<T> succ()
{
return succ;
}
public void changerSucc(Liste<T> y)
{
succ = y;
}
public void changerPred(Liste<T> y)
{
pred = y;
}
}
这是一个链表的简写,每一层包含了上一个元素,这一个元素,下一个元素
- 哈希表,通过建立KV关系查找,相比于之前的顺序访问或者其他指数访问要快。
import java.util.HashMap;
public class TestHash
{
public static void main(String[] args)
{
HashMap<String,String> annuaire = new HashMap<String,String>();
// ajout des valeurs
annuaire.put("Alfred","2399020806");
annuaire.put("Daniel", "2186000000");
// obtention d'un numéro
if (annuaire.containsKey("Danielle"))
{
String num = annuaire.get("Danielle");
System.out.println(Danielle : "+num");
}
else
{
System.out.println("pas trouve");
}
}
}
一般包含结点,结点的度(该结点下有多少子树的数目),树的度
不同的遍历方法:
前序遍历,首先结点,然后左子树,右子树
中序遍历,左子树,结点,右子树
后序遍历,左子树,右子树,结点
层序遍历,从上到下,从左到右
class Arbre
{
protected <T> valeur;
protected Arbre filsGauche, filsDroit;
public <T> valeur()
{
return valeur;
}
public boolean existeFilsGauche() { return filsGauche != null; }
public boolean existeFilsDroit() { return filsDroit != null; }
public Arbre filsGauche() { return filsGauche; }
public Arbre filsDroit() { return filsDroit; }
public void affecterValeur(<T> c) { valeur = c; }
public void affecterFilsGauche(Arbre g) { filsGauche = g; }
public void affecterFilsDroit(Arbre d) { filsDroit = d;}
public boolean feuille() {return (filsDroit==null &&
filsGauche==null);
}
public int hauteur()
{
int g = existeFilsGauche() ? filsGauche.hauteur() : 0;
int d = existeFilsDroit() ? filsDroit.hauteur() : 0;
return Math.max(g,d) + 1 ;
}
// Constructeurs
public Arbre(T val)
{
valeur = val;
filsGauche = filsDroit = null;
}
public Arbre(T val, Arbre<T> g, Arbre<T> d)
{
valeur = val;
filsGauche = g; filsDroit = d;
}
// Affichage
public void afficherPrefixe()
{
System.out.print(valeur+"\t");
if (existeFilsGauche()) filsGauche.afficherPrefixe();
if (existeFilsDroit()) filsDroit.afficherPrefixe();
}
public void afficherInfixe()
{
if (existeFilsGauche()) filsGauche.afficherInfixe();
System.out.print(valeur+"\t");
if (existeFilsDroit())filsDroit.afficherInfixe();
}
public void afficherPostfixe()
{
if (existeFilsGauche()) filsGauche.afficherPostfixe();
if (existeFilsDroit())filsDroit.afficherPostfixe();
System.out.print(valeur+"\t");
}
二叉排序树是指左子树小于结点小于右子树,而且结点值不重复。判断是否为二叉排序树:
public boolean superieur(char x)
{
// vrai si x est supérieur à tous les éléments de l’arbre
if (feuille()) return (x>=valeur);
else return
(((this.existeFilsGauche())? (this.filsGauche).superieur(x):true) &
((this.existeFilsDroit())? (this.filsDroit).superieur(x):true));
}
public boolean inferieur(char x) {//similaire a superieur ... }
public boolean binrech() {
if (feuille()) return true;
else return
((existeFilsGauche()?(filsGauche.superieur(valeur) && filsGauche.binrech()):true) &
(existeFilsDroit()?(filsDroit.inferieur(valeur) && filsDroit.binrech()):true));
}
5. 常用数据结构方法
二维数组array[][]的定义和访问
数据结构 |
vector<String> |
ArrayList<String> |
LinkedList<String> |
HashMap<String,int> |
添加 |
add(i, str) |
add(i,str) |
add(i,str) |
put(str,i) |
查找 |
get(i) |
get(i) |
get(i) |
get(str) |
索引 |
indexOf(str) |
indexOf(str) |
indexOf(str) |
|
删除 |
remove(i)/remove(str) |
remove(i/str) |
remove(i/str) |
remove(i) |
清除 |
clear() |
clear() |
clear() |
|
查看大小 |
size() |
size() |
size() |
size() |
迭代器 |
iterator() |
iterator() |
iterator() |
|
变成数组 |
|
toArray() |
toArray() |
|
hashmap还可以返回键值对entryset(),也可以判断是否含有key和value,containsKey(),containsValue()
Hashmap创建的时候需要继承
TP整理
- 定义构造函数时也需要声明权限修饰符,构造函数不需要返回值,调用的时候直接在声明一个对象的时候调用
- 访问成员变量的时候用.
- 方法中除了构造函数都需要权限修饰符和返回类型名
- 在类中调用成员变量可以直接调用
- 字符串之间用+连接
- 当一个类中有main函数时,一般这么定义: public static void main(String[] a){}
- 在定义类的时候不要有()
- 向量的创建和声明: Vector<T> mesObjectsG = new Vector<T>();
- 打印的使用: System.out.println()
- 成员函数在类的开头只是声明,并没有创建,所以在方法中创建
- for循环的使用: for(Point p : seg.getVecP())
- Vector.add(), 向量的添加
- Vector.get(i), i从0开始, 向量的访问
- Vector.size()返回int值,是vector的大小
- TP1中为了让图形可视化,每个类都需要extends ObjectGraphique
- 什么时候需要在类定义方法时new一个对象: 当这个对象来自其他类同时改变这个对象会对新创建的类产生影响,所以一般还是new一个对象比较好
- 基本的数据类型: int, string, float, boolean不需要new, 声明的时候也不需要构造函数
- 继承的时候可以用super()来调用继承类的构造函数
- 异常的抛出: 在定义类中的方法的时候,需要抛出的方法需要在创建时添加一句throws Exception, 调用的时候使用throw new Exception(“…”)
- 也可以throws IOException这样已经定义好的抛出类型
- 文件读入: Reader reader = new FileReader(textname.txt)
- 逐行读入: BufferedReader in = new BufferedReader(reader); String line = in.readline()
- 分词器: StringTokenizer st = new StringTokenlizer(line, DeleteChar); 然后就可以像迭代器一样调用, if(st.hasMoreTokens()){st.nextToken()}
- 文件写入: Writer writer = new FileWriter(newtextname); writer.write(“…”)
- 将链表中所有的单词写入一个文件: for (object k : this){writer.write(k+”\n”);writer.flush()} 写入完毕后, writer.close()
- 哈希表判断key是否在哈希表中: HashMap.containsKey(…), 返回值为布尔类型
- 哈希表中添加元素: HashMap.put(key, value)
- 哈希表可以返回键值对,键对和值对,调用HashMap.entrySet()、HashMap.keySet()、HashMap.valueSet()
- 通过键来访问哈希表中的值: HashMap.get(key)
- EntrySet同样可以通过getKey()和getValue()来访问键值
- 在创建一个新类时,对于类的名字可以这么取: Arbre<T>, 这样就表示Arbre类中的数据类型是T
- java中的空是null,小写
- 记住二叉树高度是怎么写的
- 记住二叉树前序中序后序遍历是如何写的
- 在进行没有变量x时怎么计算数的结果: 先用迭代访问出左值和右值,然后根据根结点的符号决定进行什么运算
- Integer.parseInt(String a)的作用是将整数的String表示转化为Integer
- 对于含变量x的二叉树如何在输入x的值的情况下算出结果: 首先遍历左子树,如果左子树的左边有x,那么将输入的值赋给这个结点的x,然后迭代回来计算左结点的值,具体的可以看网站截图
- java中final关键字是保证了变量无法修改,只能访问
- 字符串的比较用.equals()
- Vector.contains(…)可以判断一个值是否在这个向量里
- String.charAt(i), 可以将字符串第i个字符赋给char
- instanceOf用来判断一个对象是不是一个类的实例: if (a instanceOf A)
- 多态的一种应用是: 抽象父类,子类继承抽象父类
Comments