[TOC]

第六讲 面向对象初步

6.1 类和对象的基本概念

  • **对象(object)**表示现实世界中可以明确识别的实体。

例如,学生、圆、按钮等。对象具有状态和行为。

  • **类(class)**定义了同一类对象共有的属性和方法。

类是对象的模板、蓝图。对象是类的实例。

面向对象的三大特征:封装、继承、多态。

6.1.1 使用构造方法构造对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Circle {
double radius = 1.0;//数据域

Circle() {
radius = 1.0;
}//构造方法
Circle(double r) {
radius = r;
}//构造方法

double getArea() {
return radius * radius * 3.14159;
}//实例方法
}

如果不写构造方法,系统会赠送一个无参的构造方法。

构造方法与一般方法有三点不同:

1:构造方法必须与所在类具有相同的名字。

2:构造方法没有返回类型,甚至连void也没有。

3:一般方法的调用是显示调用(方法名后面跟实参),而构造方法是隐式调用,其调用时机是在使用new操作符创建对象时。

6.1.2 通过引用变量访问对象

对象是引用类型,通过引用变量进行访问,引用变量中存储的是对象的引用(reference)。

在java中,数组被看作是对象。

(1)声明引用变量

例如:

1
Circle myCircle;

(2)引用变量赋值

例如:

1
myCircle = new Circle();

(3)使用new操作符创建对象

例如:

1
2
3
4
new Circle(); //调用无参构造方法
new Circle(5); //调用带有一个参数的构造方法

Scanner input = new Scanner(System.in);

6.1.3 访问对象的数据和方法

(1)访问对象实例的属性

例如:

1
myCircle.radius

(2)调用对象的方法:

例如:

1
myCircle.getArea()

6.2 使用java库中的类

6.2.1 Date类

1
java.util.Date;

(1)构造方法

Date():以当前时间毫秒值创建Date对象
Date(long time):以指定的毫秒值创建Date对象

(2)成员方法

long getTime():获取Date对象的毫秒值
setTime(long time):设置Data对象的毫秒值

1
2
3
java.util.Date date = new java.util.Date();
System.out.println(date.getTime());
System.out.println(date.toString());

输出:毫秒数/字符串时间

6.2.2 Random类

1
java.util.Random;

(1)构造方法

Random():以当前时间毫秒值作为种子,创建Random对象
Random(long seed):以指定种子创建Random对象

(2)成员方法

nextInt():生成1个int类型范围的随机数
nextInt(int n):产生1个[0,n-1]范围内的随机数

(3)生成0~n之间的数

1
2
①(int)Math.random()*(n+1)
②Random r = new Random();

r.nextInt(m)表示生成[0,m-1]之间的随机数,也就是说random.nextInt(m+1),将生成[0,m]之间的随机整数。
r.nextInt(n+1)

(4)生成n~m之间的随机数

1
2
①n+(int)(Math.random()*(m+1-n));
②Random r = new Random();

r.nextInt(m+1-n)+n;

6.2.3 Math类

abs(int a):绝对值
ceil(double d):向上取整
floor(double d):向下取整
max(int a,int b):最大值
pow(double a,double b):a的b次幂
random():随机数[0.0,1.0]
round(float f):四舍五入
sqrt(double d):算术平方根

6.3 静态成员、实例成员

类中的成员有变量和方法,称为成员变量和成员方法。

对于这些成员,如果有static修饰符,则称为静态成员,

否则称为实例成员。

使用原则:

  • 方法紧密关联于具体的对象实例——实例;
  • 方法与实例五关——静态。

6.3.1 实例成员

实例变量和实例方法是属于类的某个特定实例的,对于类中定义的实例成员,其不同的对象实例都是各自独立,位于不同的内存区域。

只能通过引用变量访问,即:对象名.实例成员

1
2
3
4
5
6
7
8
9
10
11
12
public class Student {
String name;
public Student(String studentName) {
name = studentName;
}
public String getName() {
return name;
}
}//name是实例成员

Student s1 = new Student("张三");
Student s2 = new Student("李四");

6.3.2 静态成员

  • 静态变量被类的所有实例共享。
    静态方法并不绑定到某个特定的对象。

  • 调用静态成员的方式是类名.静态变量类名.静态方法

  • 静态方法中可以直接访问静态成员,但不能直接访问实例成员;

    而实例方法中访问静态和实例成员都不受限制。

1
2
3
4
5
6
7
static int num;

static int number(){
return num;
}

final static double PI=3.14;

6.4 类成员的控制访问

类中代码可以访问自身的所有成员。

6.4.1 可见性修饰符

其它类中的代码访问成员,受可见性修饰符的限制:

  • private 只能当前类自身可以访问。
  • 默认 无访问修饰符的成员,只有相同包中的代码可以访问。
  • protected 子类、同一包中的类可以访问。
  • public 所有其它类都可以访问。

6.4.2 数据域封装

•为了避免直接修改数据域(属性),应该将数据域的这些成员变量设为私有的;同时提供getter(读取器)和setter(修改器)。这称为数据域封装(ecapsulation)。

•假设成员变量名为xxx,getter方法和setter方法通用的命名规则为getXxx()和setXxx(参数列表),对于布尔型的读取器一般命名为isXxx()。

get方法返回值,set方法设置值。

其实就只是命名改了而已。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Circle {
private double radius;
public double getRadius() {
return radius;
}//get方法//////

public void setRadius(double newRadius) {
if (newRadius > 0) {
radius = newRadius;
} else {
System.out.println("半径设置有误");
}
}//set方法/////

public Circle() {
radius = 1.0;
}
public Circle(double newRadius) {
radius = newRadius;
}
double getArea() {
return radius * radius * Math.PI;
}
}

6.4.3 this引用

  • this表示当前对象实例

    set方法经常把数据域名用作参数名,这个时候数据域就被隐藏。

    如果一个局部变量和一个类变量具有相同的名字,那么局部变量优先,同名的类变量被隐藏。

    实例变量被局部变量或方法参数隐藏,可以通过this.x访问实例变量。(隐藏的静态变量用“类名.静态变量”引用即可)。

  • 调用类的其它构造方法。

6.5 对象数组

与基本数据类型一样,可以声明并创建对象数组。

当创建对象数组时,数组元素的缺省初值为null。

1
2
3
4
Circle[] circleArray = new Circle[10];
for(int i = 0; i < circleArray.length; i++) {
circleArray[i] = new Circle();
}

第七讲 字符串

7.1 字符串的操作

String对象是不可改变的,字符串一旦创建,内容不能再改变。

7.1.1 创建字符串对象

(1)常规形式创建字符串

1
String s1 = new String("Welcome to java");

(2)简写形式

1
String s2 = "Welcome to java";

(3)用字符数组创建字符串

1
2
3
char[] charArray = {'G','O','O','D',' ','D','A','Y'};

String s3 = new String(charArray);

上述中,s1==s2为false。

7.1.2 字符串比较

注意:==比较的是字符串地址,equals方法比较的是字符串内容

1
"java".euqals("java");

//如果这个字符串等于括号内字符串,返回true

1
"java".euqalsIgnoreCase("JAVA");

//无视大小写的euqals方法,返回true

1
"java".compareTo("java");

//比较这个字符串和括号内字符串的大小,返回值为int(大于>0,小于<0,等于==0)

1
"java".compareToIgnoreCase("JAVA");

//无视大小写的compareTo方法

1
"java".startsWith("j");

//如果这个字符串以指定前缀开始则返回true

1
"java".endsWith("a");

//如果这个字符串以指定前缀结束则返回true

7.1.3 获取字符串长度

1
2
3
s1="Welcome";

s1.length();

返回7

7.1.4 获取指定位置的字符

•charAt(index)方法可以获取指定位置的字符。index是字符串的下标值,index的值必须在0到s.length()-1之间。

•例如,message.charAt(0)返回’W’,messageCharAt(14)返回’a’。

7.1.5获取子串

1
2
3
String s1 = "Welcome to java";

String s2 = s1.substring(0,11);

//开始到结束区间为:左闭右开

1
String s3 = s1.substring(0);

值为:s2=”Welcome to “; s3=”Welcome to java”;

7.1.6 字符串的转换

•toLowerCase将字符串转换成小写形式

•toUpperCase将字符串转换成大写形式

•trim删除两端的空格

例如:

“ Welcome “.trim()返回一个新字符串Welcome。

7.1.7 查找指定的字符或字符串

1
"Welcome to java".indexOf('x');

//查找不到x,返回-1

1
"Welcome to java".indexOf('e');

//只查找第一个e,返回1

1
"Welcome to java".indexOf('e',2);

//规定查找的起始位置,返回6

1
"Welcome to java".indexOf("come");

//可以查找字符串,返回3

1
"Welcome to java".lastIndexOf("e");

//从后往前查找,找到字符串中最后一个e的位置,返回6

1
"Welcome to java".lastIndexOf("e",0);

//返回-1

应用:如何获取用户的后缀名?

后缀名是紧随在”.”后的字符串,先用lastIndexOf(“.”)获取”.”在文件名中的索引位置k,然后使用subString(k+1)就可以得到完整的后缀名

7.1.8 字符串的分割

1
"Java#HTML#Ruby".split("#");

//其参数为String类型,代表用于分割字符串的定界符,返回结果就是字符串数组

//返回”Java”,”HTML”,”Ruby”

1
"Java.HTML.Ruby".split(".");

//返回值为空

7.2 字符串类型转换

1
2
int intValue = Integer.parseInt(intString);
int i = Integer.parseInt(s:"45");

//i:45

1
2
double doubleValue = Double.parseDouble(doubleString);
double d = Double.parseDouble(s:"23.4");

//d:23.4

1
2
String s = doubleValue + **""**; 
String s1 = " "+45.6

//s1:45.6

1
Integer.ToString(intValue);
1
2
3
String.valueOf(intValue);

String s3 = String.valueOf(34);

//s3:34

第八讲 继承和多态

8.1 使用super关键字

  • 父类的构造方法不能被继承。
  • 它们被显式或隐式地调用。
  • 使用super关键字显式调用。

构造方法可以调用重载的构造方法或它的父类的构造方法。如果它们都没有被显式调用,那编译器就会自动地将super()作为构造方法的第一条语句。

8.1.1 调用父类的构造方法

为了保证父类的构造方法第一时间得到运行, super的语句一定要是子类构造方法中的第一条语句,这是显式调用父类构造方法的唯一方式。

public Circle(double radius,
String color, boolean filled) {
this.radius = radius;
setColor(color);
setFilled(filled);
}

等价于——

public Circle(double radius,
String color, boolean filled) {
super(color,filled);
this.radius = radius;

8.1.2 调用父类的方法

•super.方法名(参数)

public void printCircle() {
System.out.println(“The circle is created “ +
getDateCreated() +
“ and the radius is “ + radius);
}

等价于——

public void printCircle() {
System.out.println(“The circle is created “ +
super.getDateCreated() +
“ and the radius is “ + radius);
}

8.1.3 方法重写

要重写一个方法,需要在子类中使用和父类一样的签名以及一样的返回值类型来对该方法进行定义。

方法名、参数、返回值相同。

super.toString()

重写意味着在子类中提供一个对父类已有方法的新的实现。

方法重写发生在通过继承而相关的不同类中。

8.1.4 方法重载

重载意味着使用同样的名字但是不同的方法签名来定义多个方法。

方法重载可以发生在同一个类中,也可以发生在通过继承而相关的不同类中。

重写标注:@Override

8.2 toString()方法

•在Object类中定义了public属性的toString()方法,而Object是所有类的直接或间接父类,该方法会被子类继承。

•默认的toString()方法返回的结果,是类似于类名@15037e5这样的字符串。

调用一个对象的toString()方法,会返回一个描述该对象的字符串。

1
2
Loan loan = new Loan();
System.out.println(loan.toString());

8.3 对象转换

•可以使用转换把一种类类型的对象转换为继承体系结构中的另一种类类型的对象。

•在基本数据类型转换中有隐式转换和强制转换,对象转换也有类似概念。

1
Object o = new Student()

// 隐式转换,也称为向上转型

1
Student b = (Student)O; 

//显式转换,用于子类实例转换为父类实例,即向上转换

•使用instanceof运算符来检测一个对象是否是一个类的实例:

1
Fruit f = new Apple();

那么

f instanceof Apple 将返回 true

f instanceof Orange 将返回false

8.4 多态

含义:

多态意味着父类的变量可以指向子类对象 ,当调用该父类变量的一些成员方法,其行为可以表现为子类同名方法的行为特征,而不是父类同名方法的特征。

这样就会出现这样一个情况:相同类型的变量,调用同一个方法时呈现出不同的行为特征,所以称为多态。

实现多态要点:

1、父类定义需要被重写的方法;

2、子类重写父类的方法;

3、将子类的对象实例赋值给父类类型的变量,则可通过该变量调用被重写的方法,自动调用子类的不同的重写版本。