
什么是面向对象?
1.面向对象是一种编程思想
现实生活中存在各种形态不同的事物,这些事物之间存在这各种联系。在程序中使用对象映射现实中的事物,使用对象的关系来描述现实中事物之间的联系,这种思想就是面向对象。
2.面向对象有三个主要特点:
①封装性
②继承性
③多态性
类与对象
在面向对象中,为了做到让程序中对事物的描述与事物在现实中的形态保持一致,面向对象思想中提出了两个概念:类与对象
例如:在现实生活中,“学生”这个群体可以作为一个“类”,而一名具体的学生就可以称为“对象”,这名具体的学生会有自己的姓名、年龄等信息,这些信息在面向对象中称为属性,这名学生会打篮球和看书,而打篮球和看书在类中称为“方法”
1.类的定义
在面向对象思想中最核心的就是对象,而创建对象的前提就是需要定义一个类(正如我们上面举的学生的例子,如果没有“学生”这个概念,那么世界上将不再有学生,可能叫成其它的名字了),类是java中一个重要的引用数据类型,也是java程序的基本要素,所以java程序都是基于类的。
类是对象的抽象(正如上面举到的例子,“学生”这个群体是对每一名具体的学生的总称),用于描述一组对象的共同特征和行为。类中可以定义成员变量(是用于描述对象的属性)和成员方法(是用于描述对象的行为,简称为“方法”)
类的定义格式如下:
class 类名{
成员变量;
成员方法;
}
按上述格式定义一个成员变量包括姓名、年龄、性别,成员方法为study()的类:
1.class student { //类名为student
2. String Name;
3. String Age;
4. String Sex;
5. void study(){
6. System.out.println(Name+"正在学习"); //成员方法可以直接访问成员变量
7. }
区分局部变量和成员变量:
1. class student {
2. String Name = "小明"; //类中方法之外定义的变量称为成员变量
3. String Age;
4. String Sex;
5. void study(){
6. String Name = "小红"; //方法中的定义的变量为局部变量
7. System.out.println(Name+"正在学习"); //此时访问的是局部变量
8. }
9. }
2.对象的创建与使用
要想使用一个类则必须要有对象,在java中可以使用new关键字来创建对象,格式如下:
//第一种格式(分为声明对象和实例化对象两步)`
类名 对象名称 = null; //声明对象
对象名称 = new 类名();//实例化对象(这里的实例化和初始化的意义一样)
//第二种格式(一般都用这一种格式来创建对象)
类名 对象名称 = new 类名();
student stu = new student();/*new student()用于创建student类的对象,student stu则是声明了一个student
类的变量,运算符“=”将新创建的student类的对象的地址传给了stu
示例如下:
1.class student {
2. String Name = "小明";
3. void study(){
4. String Name = "小明";
5. System.out.println(Name+"正在学习");
6. }
7.}
8.class adw {
9. public static void main(String[] args) {
10. student stu1 = new student();
11. }
12.}
上述代码在main方法中实例化了一个student对象,对象名称为stu1。使用new关键字创建的对象在堆内存空间,
stu1对象的内存分配如下:

从图中可以看出,对象名称保存在栈中,而对象的属性信息则保存在对应的堆空间中
创建对象后,可以使用对象访问类中的某个属性或方法,格式如下:
对象名称.属性名;
对象名称.方法名;
下面通过一个案例学习如何访问对象的属性和方法:
1.class student {
2. String Name;
3. void study(){
4. System.out.println(Name+"正在学习");
5. }
6.}
7.class adw {
8. public static void main(String[] args) {
9. student stu1 = new student();
10. student stu2 = new student();
11. stu1.Name = "小明";//为stu1对象的Name属性赋值
12. stu1.study(); //调用对象stu1的方法
13. stu2.Name = "小红";//为stu2对象的Name属性赋值
14. stu2.study(); //调用对象stu2的方法
15. }
16.}
stu1和stu2对象的内存分配如下:

对象的引用传递
类属于引用数据类型,引用数据类型就是指内存空间可以同时被多个栈内存引用,下面通过一个案例讲解对象的引用传递:
1.class Student {
2.String Name;
3.int Age;
4. void read(){
5. System.out.println(Name+Age);
6. }
7.}
8.public class adw {
9. public static void main(String[] args) {
10. Student stu1 = new Student();
11. Student stu2 = null;
12. stu2 = stu1; //使stu1和stu2指向同一块空间
13. stu2.Name = "小黑子";
14. stu1.Name = "小明";
15. stu1.Age = 20;
16. stu2.Age = 50;
17. stu1.read();//运行结果为:小黑子50
18. stu2.read();//运行结果为:小黑子50
19. }
20. }

注意:一个栈内存空间只能指向一个堆内存空间,但一个堆内存空间可以被多个栈内存空间所指
访问控制
java提供了4种访问控制权限,按级别从小到大分别是private、default、protected和public。
private:private属于私有访问权限,用于修饰类的成员变量和成员方法,类的成员变量或成员方法一旦使用private关键字,则该成员只能在本类中被访问
default:default属于默认访问权限,如果一个类中的成员变量或成员方法没有被任何访问控制权限声明,则这个成员变量或成员方法可以在所在包内的所有类中被访问,但是不能在其它包中的类中被访问。
protected:protected属于受保护的访问权限,一个类的成员变量或成员方法被protected修饰,在此成员变量或成员方法只能在所在包内的所有类中和其他包的子类中被访问。
public:类的成员变量或成员方法一旦使用public关键字,则该成员变量或成员方法能在所有类中被访问。

1.class ade {
2. public int aa; //aa可以被所有的类访问
3. protected boolean bb; //bb可以被所有子类以及本包中所有类使用
4. void cc(){
5. System.out.println("包访问权限");
6. }
7. private class InnerClass{ //InnerClass是private权限的内部类,只能在本类中使用
8. }
9.}
需要注意的是类名只能用public修饰或不加修饰符,局部成员是没有访问权限控制的,因为局部成员只能在其所在的作用域内起作用,不可能被其它类访问到。错误的代码示例如下:
11.class ade {
12.{
13.public int aa; //错误,局部变量没有访问控制权限
14.}
15. void cc(){
16. System.out.println("包访问权限");
17. }
18. private class InnerClass{ //InnerClass是private权限的内部类,只能在本类中使用
19. }
20.}
封装性
封装是面向对象的核心思想,理解并掌握封装性对学习面向对象很重要
1.为什么要封装?
在java面向对象的思想中,封装可以被认为是一个保护屏障,下面举一个例子解释什么是封装:
1.class Student {
2. String name;
3. int age;
4. void read(){
5. System.out.println("全民制作人大家好,"+"我是"+name+","+"年龄"+age);
6. }
7.}
8.public class adw {
9. public static void main(String[] args) {
10. Student stu1 = new Student();
11. stu1.name = "小黑子";
12. stu1.age = -100;//-100显然是一个不合理的值,但在程序中却没有任何问题,为避免这种错误的发生,在设计类的时候需对成员变量的访问做出一些限定,不允许外界随意访问,这就需要实现类的封装
13. stu1.read();
14. }
15. }
2.如何实现封装?
类的封装是指将对象的状态信息隐藏在对象的内部,不允许外部程序直接访问对象的信息,而是通过该类提供的方法是实现对对象的信息的操作和访问
实现封装的步骤:在定义一个类的时候,将类中的属性私有化,即使用private关键字修饰类的属性,被私有化的属性只能在类中被使用,如果外界想要访问私有属性,则必须通过类中的setter方法(设置属性值)和setter方法(获取属性值)
1.class Student {
2. private String Name;
3. private int Age;
4. public String getName() {
5. return Name;
6. }
7. public void setName(String Name) {
8. this.Name = Name;
9. }
10. public int getAge() {
11. return Age;
12. }
13. public void setAge(int Age) {
14. if(Age>=0)
15. this.Age = Age;
16. else
17. System.out.println("error");
18. }
19. public String toString() {
20. return "Student{Name:" + Name + ", Age:" + Age + "}";
21. }
22. public void read() {
23. System.out.println(Name+Age);
24. }
25.}
26.public class adw {
27. public static void main(String[] args) {
28. Student stu1 = new Student();
29. stu1.setName("小明");
30. stu1.setAge(100);
31. System.out.println(stu1.getName()); //小明
32. System.out.println(stu1.getAge()); //100
33. System.out.println(stu1.toString());//Student{Name:小明, Age:100}
34. stu1.read(); //小明100
35. }
36. }
构造方法
1.定义构造方法
构造方法是特殊的成员方法。在定义时,有以下几点需要注意:
①构造方法名必须与类名一致
②构造方法名称前不能有返回值类型
③不能在构造方法中使用return返回一个值,但是可以单独写return语句作为方法的结束
实例化对象后,要为对象的属性赋值,可以通过直接赋值或setter方法来赋值。如果要在实例化对象的同时为此对象的属性赋值,可以运用有参构造方法。因为实例化对象的同时会运行对象中的构造方法
1.class Student {
2. public Student(){
3. System.out.println("调用了无参构造方法");
4. }
5.}
6.public class adw {
7. public static void main(String[] args) {
8. Student stu1 = null;
9. stu1 = new Student(); //运行结果:调用了无参构造方法
10. }
11. }
1.class Student {
2. public Student(){
3. System.out.println("调用了无参构造方法");
4. }
5.}
6.public class adw {
7. public static void main(String[] args) {
8. Student stu1 = null;
9. stu1 = new Student(); //运行结果:调用了无参构造方法
10. }
11. }
1.class Student {
2. String Name;
3. int Age;
4. public Student(String n,int i){
5. System.out.println("调用了有参构造方法");
6. Name = n;
7. Age = i;
8. }
9.}
10.public class adw {
11. public static void main(String[] args) {
12. Student stu1 = null;
13. stu1 = new Student("大大",19);
14. System.out.println(stu1.Name+stu1.Age); //大大19
15. }
16. }
1.class Student {
2. private String Name;
3. private int Age;
4. public Student(String n,int i){
5. System.out.println("调用了有参构造方法");
6. Name = n;
7. Age = i;
8. }
9. public void read(){
10. System.out.println(Name+Age);
11. }
12.}
13.public class adw {
14. public static void main(String[] args) {
15. Student stu1 = null;
16. stu1 = new Student("大大",19);
17. stu1.read(); //大大19
18. }
19. }
2.构造方法的重载
与普通方法一样,构造方法也可以重载,在一个类中定义多个构造方法,只要每个构造方法的参数类型或参数个数不同即可
3.默认构造方法
在java中每个类都至少有一个构造方法,如果在定义一个类的时候没有写构造方法,那么系统会自动的为这个类创建一个默认的构造方法,这个默认的构造方法没有参数,且方法体中没有任何代码,即什么也不做。
1.//第一种写法
2.class Student{
3.}
4.//第二种写法
5.class Student{
6. public Student(){
7. }
8.}
对于第一种写法,类中虽然没有定义构造方法,但仍然可以使用new Student()语句创建Student类的对
象,在实例化对象时调用默认的构造方法。
由于系统提供的构造方法往往不能满足我们的需求,因此,常常需要程序员自己定义构造方法,一旦定义
了构造方法,系统就不再提供默认的构造方法了
注意:构造方法通常使用public进行修饰
this关键字
①使用this关键字调用本类中的属性
②使用this关键字调用本类中的成员方法
③使用this关键字调用本类中的构造方法
1.package zhiyin;
2.import java.util.Scanner;
3.class test{
4. String name;
5. public void setName(String name) {
6. this.name = name;
7. System.out.println("setName: " + this.name);
8. }
9. public void thisTest(String name) {
10. this.setName(name); //this关键字调用本类中的成员方法
11. System.out.println("thisTest: " + this.name);
12. }
13.}
14.public class adw {
15. public static void main(String[] args) {
16. test tt = new test();
17. tt.setName("Yida");
18. tt.thisTest("Jenny");
19. }
20.}
构造方法是一个类的对象在通过new关键字创建时自动调用的,在程序中不能向调用其他方法一样通过方法名(也就是类名)来调用。但如果一个类有多个构造方法,可以在一个构造方法中通过this(paras…)来调用其他的构造方法。
使用this来调用其他构造方法有如下几个约束:
·只能在构造方法中通过this来调用其他构造方法,普通方法中不能使用。
·不能通过this递归调用构造方法,即不能在一个构造方法中通过this直接或间接调用该构造方法本身。
·通过this调用其他构造方法必须放在构造方法的第一行中执行。
·由于super调用父类的构造函数也必须放在构造方法的第一行中执行,因此,通过this和super调用构造方法不能同时出现一个构造方法中。也不能在一个构造方法中多次调用不同的构造方法
1.//以下代码是错误的,因为通过this关键字,形成了递归调用:
2.class test {
3. test() {
4. this(1);
5. }
6. test(int a){
7. this();
8. }
9. test(int b) {
10. this(1, 2);
11. }
12.}
正确示例:
1.package zhiyin;
2.class Student { //定义一个类,类的名字为student。
3. public Student() { //定义一个方法,名字与类相同故为构造方法
4. this("Hello!"); //调用Student(String)
5. }
6. public Student(String name) { //定义一个带形式参数的构造方法
7. System.out.println(name);
8. }
9.}
10.public class adw {
11. public static void main(String[] args) {
12. Student stu = new Student(); //Hello!
13. Student stu1 = new Student("world!"); //world!
14. }
15.}
static关键字
当我们希望某些属性被所有对象共享,就必须将此属性声明为static属性。如果属性使用了static关键字修饰,则该属性可以直接用类名进行调用和访问,除了修饰属性,static关键字还可以修饰成员方法
1.静态属性
如果在java中使用static修饰某个属性,则称该属性为静态属性(也称全局属性),静态属性可以通过类名直接访问,访问格式如下:
类名.属性名
先看一个案例:
1.package zhiyin;
2.class Student { //定义一个类,类的名字为student。
3. String name;
4. int age;
5. String sc = "A 大学";
6. public Student(String name,int age){
7. this.name=name;
8. this.age=age;
9. }
10. public void info() {
11. System.out.println("姓名:"+this.name+",年龄:"+this.age+",学校:"+sc);
12. }
13.}
14.public class adw {
15. public static void main(String[] args) {
16. Student stu1 = new Student("张三",18);
17. Student stu2 = new Student("李四",19);
18. stu1.info(); //姓名:张三,年龄:18,学校:A 大学
19. stu2.info(); //姓名:李四,年龄:19,学校:A 大学
20. }
21.}
如果现在有10万个学生对象,现在想要修改这些学生的学校信息,就需要把这10万个对象的学校属性全部修改,共修改10万遍,这是很麻烦的。为解决上述问题,可以使用static修饰sc属性,这样sc属性只会被分配一块内存空间,被Student类的所有对象共享,只要某个Student对象对sc属性进行了一次修改,那么全部对象的sc属性值都会跟着变化。对上述代码修改如下:
1.package zhiyin;
2.class Student { //定义一个类,类的名字为student。
3. String name;
4. int age;
5. static String sc = "A 大学";
6. public Student(String name,int age){
7. this.name=name;
8. this.age=age;
9. }
10. public void info() {
11. System.out.println("姓名:"+this.name+",年龄:"+this.age+",学校:"+sc);
12. }
13.}
14.public class adw {
15. public static void main(String[] args) {
16. Student stu1 = new Student("张三",18);
17. Student stu2 = new Student("李四",19);
18. stu1.sc="B大学"; //或者这样写:Student.sc = "B大学"
19. stu1.info(); //姓名:张三,年龄:18,学校:B 大学
20. stu2.info(); //姓名:李四,年龄:19,学校:A 大学
21. }
22.}
注意:static不能修饰局部变量
2.静态方法
如果想要使用类中的成员方法,就需要先将这个类实例化(即创建一个这个类的对象),而实际开发时,开发人员有时希望在不创建对象的情况下,通过类名就可以直接调用某个类中的方法,想要实现这个效果,只需要在成员方法前加上static即可,这样的方法称为静态方法,同静态属性,静态方法也可以通过类名和对象访问:
类名.成员方法名;
或
对象名.方法;
代码块
简单来说,用{}括号括起来的代码就是代码块,根据位置及声明关键字的不同,代码块可以分为普通代码块、构造块、静态代码块、同步代码块
1.普通代码块
普通代码块就是直接在方法或语句中定义的代码块,示例如下:
1.package zhiyin;
2.public class adw {
3. public static void main(String[] args) {
4. {
5. int age = 18;
6. System.out.println("这是普通代码块。age:"+age);//这是普通代码块。age:18
7. }
8. int age = 30;
9. System.out.println("age:"+age);//age:30
10. }
11.}
在上述代码中,每一对{}括起来的代码都称为一个代码块,adw是一个大的代码块,在adw代码块中包含了main()方法代码块,在main()方法中又包含一个局部代码块,局部代码块对main()方法进行了分割,起到了限定作用域的作用。局部代码块中定义了变量age,main()方法代码块中定义了变量age,但由于两个变量在不同的代码块,作用域不同,因此并不相互影响。
2.构造代码块(简称构造块)
直接在类中定义的代码块称为构造代码块。
1.package zhiyin;
2.class Student{
3. String name;
4. {
5. System.out.println("我是构造代码块");
6. }
7. public Student(){
8. System.out.println("我是Student类的构造方法");
9. }
10.}
11.public class adw {
12. public static void main(String[] args) {
13. Student stu1 = new Student();
14. Student stu2 = new Student();
15. }
16.}
运行结果:
可以看出,在实例化对象stu1、stu2时,都先输出了“我是构造代码块”,表明在实例化对象的时候不仅会自动执行构造块,而且代码块的执行顺序要先于构造方法(这里的执行顺序与构造块写在构造方法前面还是后面是无关的)
3.静态代码块
用static修饰的代码块称为静态代码块
静态代码块只在类第一次使用时才会被加载,并且只会加载一次(即静态代码块只会执行一次)
1.package zhiyin;
2.class Student { //定义一个类,类的名字为student。
3. {
4. System.out.println("我是构造代码块");
5. }
6. static {
7. System.out.println("我是静态代码块");
8. }
9. public Student() {
10. System.out.println("我是Student类的构造方法");
11. }
12.}
13.public class adw {
14. public static void main(String[] args) {
15. Student stu1 = new Student();
16. Student stu2 = new Student();
17. Student stu3 = new Student();
18. }
19.}
运行结果:

注:参考《JAVA基础案例教程第二版》