面向对象(OOP)概述
- 面向过程:分析出解决问题所需要的步骤
- 面向对象:Java是完全面向对象的语言,Java程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分;只要对象能够满足要求,不关心其功能的具体实现 三大特性:封装、继承、多态
- 区别:举例
什么是类与对象?
- 类与对象:类是对象的模板,对象是类的一个个体(实例)
- 类之间的关系:
- 依赖:uses-a,一个类的方法操纵另一个类的对象,应尽量降低类之间的耦合
- 聚合:has-a,类A的对象包含类B的对象
- 继承:is-a,特性与共性
- 定义类 & 对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Employee { //定义Employee类 = 属性 + 方法
String name; //定义属性(成员变量)
double salary;
public void info() { //方法:输出name & salary
System.out.println("姓名:" + name + ";薪资:" + salary);
}
}
//一个类定义完成,仅仅是概念上的定义,抽象的,必须产生对象
public class EmployeeTest {
public static void main(String[] args) {
Employee emp = new Employee(); //创建对象并实例化
emp.name = "张三"; //访问属性:对象名称.属性
emp.salary = 6666;
emp.info(); //访问方法:对象名称.方法
}
}
构造方法
- 要想使用对象,必须先构造对象;在对象实例化时就会调用构造方法;
- 构造方法的名称必须与类名称一致;
- 构造方法的声明处不能有任何返回值类型的声明
- 不能再构造方法中使用return返回一个值
- 如果没有自定义构造方法,则自动生成一个构造方法public 类名(){};如果定义了一个构造方法,不管该构造方法是否有参数,都不会生成默认的构造方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Employee {
String name;
double salary;
public Employee(double s) {
this.salary = s;
System.out.println("姓名:" + name + ";薪资:" + salary);
}
}
public class ConstructorTest {
public static void main(String[] args) {
System.out.println("声明对象:Employee emp = null;");
Employee emp = null;
System.out.println("emp = new Employee(6666);");
emp = new Employee(6666); //实例化才调用构造方法
}
}
构造方法重载与普通方法一样,会根据参数类型、个数、顺序不同调用不同的构造方法
1
2匿名对象
成员变量 & 局部变量
成员变量指的是在类里定义的变量;局部变量指的是在方法里定义的变量
- 成员变量可以被访问控制符及static修饰,局部变量不能被访问控制符及static修饰;两者都可以定义成final常量
- 成员变量存储在堆,局部变量存储在栈。局部变量的作用域仅限于定义它的方法,在该方法的外部无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它。如果访问权限允许, 还可以在类的外部使用成员变量
- 局部变量的生存周期与方法的执行期相同:当方法执行到定义局部变量的语句时,局部变量被创建;执行到它所在的作用域的最后一条语句时,局部变量被销毁。类的成员变量,如果是实例成员变量,它和对象的生存期相同。而静态成员变量的生存期是整个程序运行期。
- 成员变量有默认值,基本类型的默认值为 0,复合类型的默认值为null。(被final修饰且没有static的必须显式赋值),局部变量不会自动赋值,所以局部变量在定义后先要赋初值,然后才能使用
- 局部变量可以和成员变量同名,且在使用时,局部变量具有更高的优先级 不推荐
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41class Variable {
//成员变量,显示初始化
public static String name01 = "类变量";
public String name02 = "实例变量";
//成员变量,未初始化,new创建实例时默认初始化
public static String name03;
public String name04;
public void info01( ) { //定义方法
//int i; //局部变量未初始化无法打印
//System.out.println(i);
int i = 10; //局部变量初始化
System.out.println(i); //10
}
public void info02( ) {
String name02 = "我不是实例变量"; //方法中定义同名成员变量
System.out.println(name02); //我不是实例变量
System.out.println(this.name02); //实例变量
}
}
public class VariableTest {
public static void main(String[] args) {
//未创建实例前,可以调用类变量,无法调用实例变量
System.out.println(Variable.name01); //类变量
Variable var = new Variable();
//实例化后,可以调用实例变量
System.out.println(var.name02); //实例变量
//成员变量未初始化,会默认初始化
System.out.println(Variable.name03); //null
System.out.println(var.name04); //null
//实例化后的对象可以调用类变量,会有警告!不推荐!
System.out.println(var.name01);
//实例对象可以改变类变量值,不推荐!
var.name01 = "实例对象改变了类变量";
System.out.println(var.name01);
var.info01(); //10
//System.out.println(i); 定义在方法中的局部变量i出了方法无法访问
//方法中的局部变量可以与局部变量同名,且优先调用
var.info02();
}
}
Java传递机制:值传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104/*
* 在这里需要对Java的传递机制进行了解:
* Java总是采用“按值传递”
*
* 一些概念:
* 值传递:函数在调用的时候,传递的参数不是实参本身,而是它的副本(拷贝)
* 引用传递:函数在调用的时候,传递的参数就是实参本身(的地址)
*/
public class ParamTest {
public static void main(String[] args) {
/*
* 第一个测试,
* 调用的tripleValue方法不能够修改原先的数值
*/
System.out.println("Testing tripleValue:");
double percent = 10;
System.out.println("Before: percent = " + percent);
tripleValue(percent);
System.out.println("After: percent = " + percent);
/*
* 第二个测试,
* 调用的tripleSalary方法成功的改变了对象。
* 你可能会奇怪了:
* Java明明是按值传递,为什么能够改变原来的对象呢?
* 其实是因为这样的:
* Java中,对象(类的实例)都是通过引用来访问的,
* 比如:
* Object foo = new Object();
* foo只是一个引用,指向了新创建的这个Object对象
* 所以你在这里调用tripleSalary的时候,
* 传进去的harry参数本身就是一个引用了,
* 调用的方法对其进行拷贝,
* 得到的临时变量依然是与harry相同的引用,
* 所以自然就可以修改这个对象的状态了,
*
* 详细的说明可以参考这个网址:
* http://zhi.hu/MBSN
* 也可以参阅《Core Java Volume I》第122页
*/
System.out.println("\nTesting tripleSalary:");
Employee harry = new Employee("Harrt", 50000);
System.out.println("Before: salary = " + harry.getSalary());
tripleSalary(harry);
System.out.println("After: salary = " + harry.getSalary());
/*
* 第三个测试,
* 调用的swap方法并不能交换两个对象:
* 因为swap内部交换的是其拷贝过来的临时的对象,
* 而不是实际的对象
*/
System.out.println("\nTesting swap:");
Employee a = new Employee("Alice", 70000);
Employee b = new Employee("Bob", 60000);
System.out.println("Before: a = " + a.getName());
System.out.println("Before: b = " + b.getName());
swap(a, b);
System.out.println("After: a = " + a.getName());
System.out.println("After: b = " + b.getName());
}
public static void tripleValue(double x) {
x = 3 * x;
System.out.println("End of method: x = " + x);
}
public static void tripleSalary(Employee x) {
x.raiseSalary(200);
System.out.println("End of method: salary = " + x.getSalary());
}
public static void swap(Employee x, Employee y) {
Employee temp = x;
x = y;
y = temp;
System.out.println("End of method: x = " + x.getName());
System.out.println("End of method: y = " + y.getName());
}
}
class Employee {
private String name;
private double salary;
public Employee(String n, double s) {
name = n;
salary = s;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}
}
static关键字
- 静态域 & 静态方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/*staic修饰的变量/方法存储在方法区,被所有的对象所共享,它当且仅当在类初次加载时会被初始化。
而非静态变量/方法是对象所拥有的,在创建对象的时候被初始化,各个对象之间互不影响。*/
//所有对象都可以调用static公共属性,最好使用类.静态变量/方法来修改
public class Person {
String name; //成员变量
int age;
static String country; //static修饰的成员变量称为类变量/静态变量
public void info() {
System.out.println("name:" + name +",age:" + age +",Country:" + country);
Person.printInfo(); //非静态方法中可以调用静态变量/方法
}
public static void printInfo() { //静态方法
//System.out.println("name:" + name + ",Country:" + country); 静态方法不能调用非静态属性/方法
System.out.println("Country:" + country);
}
public static void main(String[] args) {
Person.country = "China"; //静态变量无需创建对象访问
Person.printInfo();
Person per1 = new Person();
per1.name = "张三";
per1.age = 20;
per1.info();
Person per2 = new Person();
per2.name = "李四";
per2.age = 22;
per2.info();
}
}
静态代码块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class Book {
public Book(String msg) {
System.out.println(msg);
}
}
public class Person01 {
Book book1 = new Book("book1成员变量初始化");
static Book book2 = new Book("static成员book2成员变量初始化");
Book book3 = new Book("book3成员变量初始化");
static Book book4 = new Book("static成员book4成员变量初始化");
public Person01(String msg) { //构造方法
System.out.println(msg);
}
public static void funStatic() { //static修饰的静态方法
System.out.println("static修饰的funStatic方法");
}
public static void main(String[] args) {
Person01.funStatic(); //未创建对象前,通过调用类的静态方法,类的静态变量初始化
Person01 p1 = new Person01("p1初始化"); //静态变量初始化后,new对象不会再次初始化
}
}
/*static成员book2成员变量初始化
static成员book4成员变量初始化
static修饰的funStatic方法
book1成员变量初始化
book3成员变量初始化
p1初始化 */理解main方法
代码块
普通、构造、静态、同步