类关系:
类之间的关系
接口之间的关系
类与接口之间的关系
正则表达式中用到的基数表示:
一对一 1:1 夫妻关系
一对多 1:m 父子关系
多对多 m: m 师生关系
0个到多个:*
0个到1个:?
1个到多个:+
1个到m个:{1,m}
n个到m个:{n,m}
m个以上:{m,}
从大的方面来说,分为三种:
一、 泛化关系(一般化关系):体现为两个关键字extends/implements
1、 extends关键字用于类继承:
a) 具体子类继承具体父类;
b) 具体子类继承抽象父类;
c) 抽象子类继承具体父类;
d) 抽象子类继承抽象父类;
2、 关键字extends用于接口继承:
a) 子接口可以继承一个父接口;
b) 子接口可以同时继承多个父接口;
子接口同时继承多个父接口的代码模拟实现:
interface Ia { void m1(); } interface Interface1 { void m2(); } interface IaInterface1 extends Ia, Interface1 { void m3(); } |
3、 类与接口之间的关系:implements
a) 具体类实现一个接口或多个接口;
代码模拟实现:
interface Ia { void m1(); } interface Ib { void m2(); } interface Ic { void m3(); } class IabcClass implements Ia, Ib, Ic { @Override public void m3() { } @Override public void m2() { } @Override public void m1() { } } |
b) 抽象类实现一个或多个接口;
i. 类实现多个接口,但只实现部分抽象方法,同时有部分抽象方法保留;
ii. 类实现多个接口,实现所有抽象方法,但方法同样标记为抽象的;
4、 同时使用extends和implements两个关键字:
a) 抽象子类继承一个具体父类的同时,实现一个或多个接口;
b) 抽象子类继承一个抽象父类的同时,实现一个或多个接口;
c)具体子类继承一个具体父类的同时,实现一个或多个接口;
d) 具体子类继承一个抽象父类的同时,实现一个或多个接口;
总结:在以上的一般化关系的多种可能性实现中,无论是extends还是implements或者兼而有之,子类或实现类与父类和接口都属于“is-a”关系。
子类对象是父类对象;
实现类是接口;
所以:接口的引用操纵具体实现类;父类引用操纵具体子类;
二、 依赖关系:
类A的对象,做为类B方法中的参数,那么就说类B依赖于类A;
属于“use-a”关系;
Person类,Car类,House类,….
代码模拟实现:
class Car { } class House { } class Person { public void buy(Car car) { System.out.println("buy car..."); } public void buy(House house) { System.out.println("buy house..."); } } |
三、 关联关系:“has-a”关系,“有一个”。
一个类对象作为另一个类中的字段,我们说两个类之间有关联关系。
作为另外类字段的类,称为从类;
包含另外类作字段的类,称为主类;
根据主类和从类的亲密程度,又可细分为三种情况:
1、 一般性关联
a) 师生关系,朋友关系等都属于一般性关联,
代码模拟实现:
class Teacher { private Student[] students; // .... } class Student { private Teacher[] teachers; // ... } |
在一般性关联关系中,主类和从类基本上谁也不会影响谁;
2、 聚合性关联
代码模拟实现:
class Horse { // ... } class Knife { // ... } class General { private Horse horse; private Knife knife; // ... } |
从聚合关联关系上说,从类影响主类更多一些;
3、 组合性关联
组合性关联关系是主从类最密切的一种;组合就是指主类由从类组成。
主类可以决定从类的生命周期。
代码模拟实现:
class Head { } class Limb { } class Leg { } class Person { private Head head; private Limb[] limbs; private Leg[] legs; // ... } |
单例类
双例类
多例类
单例类,就是设计一个类,只产生一个对象;
设计单例类的要点就是构造器是私有的;
常用的几个类的分析:
以前Math类
在学习面向过程的编程语言C时,当输出每种内置类型的数据时,都有其固定的输出格式,如整数 %d,长整型为%ld,单精度为%f,双精度为%lf等,,使用printf()方法进行输出;
到C++时,进行基于对象的语言,不再推荐使用printf()方法,而是使用ostream类的一个实例cout,用来对所有的内置数据类型进行输出,如int num=10;输出时使用std::cout<<num<<endl;即可,而且可以输出任何内置类型;因为在类定义时,对于每种内置数据类型,都进行输出重载(利用重载方法);当输出调用时,进行完全类型匹配调用;
到java或C#这些完全面向对象的语言时,进一步模糊了不同数据类型的区别,在这里,任何数据类型都可以看成是字符串,即将所有类型的数据都能统一到字符串类型中。scanf(“%d”,&num)
使用连字符“+”,可以将任何数据加上字符串,或者用字符串加上任何类型的数据,都会生成一个新的字符串;
以前常用的字符串就是字符串的实例。
String类用final关键字修饰,标明此类不能被继承;
如果用final修饰方法,标明方法不能被重写;
字符串是常量;这里指的是“字面常量”,而字面常量是不能被修改的;
字符串常量有一个创建的过程,而这个过程只有一次;
String s1 = "hello";
String s2 = "hello";
在以上两行代码中,因为引用s1的请求,请求引用一个内容为”hello”的字符串,JVM会先在字符串常量池中去查找是否存在这样一个常量,如果存在,则将常量地址赋给引用,此后就可以使用这个引用来操纵字符串;如果不存在,则在池中生成一个这样的常量字符串,将地址赋给引用;
当有其他的引用再来申请同一个内容的字符串时,此时池中已经存在这样的常量,则不会重新创建,将已经创建的字符串常量地址赋给引用即可。
这样,两个引用就引用同一个常量字符串。
String str= "how do you do?";
str=”ok”;
以上两行代码的第一行表示,当str申请字符串时,如果”how do do you?”这个字符串常量不存在,则会创建一个,将地址赋给str;如果有,则直接将地址赋给它,不会创建新的;
第二行代码表示,引用Str又来申请一个新的字符串,而将原有的字符串”how do you do?“丢弃,此时就不能再使用str访问原来的字符串。
常量字符串的存储位置:
存储在代码区域内,在代码区中,除了存储方法代码,还存储静态字段或静态常量字段,常量,两个常量池(常量字符串池,常量包装对象池);
在String类中,有一个通过字符数组生成字符串的方法:
在类中也提供了把字符串转换为数组的方法:
一个重要方法:获取字符串的长度:
String str = "You are 中国人!"; System.out.println(str.length()); // --- char chars[] = str.toCharArray(); System.out.println(chars.length); for (char c : chars) { System.out.println("\t\'" + c + "\'\t" + (int) c); } |
通过下标获取字符串的字符。
字符串包含的判定方法:
判断字符串是否以参数字符串结尾:
String[] files = new String[] { "Test11.java", "hello.class", "file.txt", "day12.doc", "c++.pdf", "Hello.java" }; for (String file : files) { if (file.endsWith("java")) { System.out.println(file); } } |
格式字符串方法:
int first = 10;
int second = 20;
// printf("%d + %d = %d\n",first,second,first+second);
构造器中有字节数组为参数
方法中可以通过字符串生成字节数组:
获取字符在字符串中的下标: