Java是一门纯面向对象的语言(简称OOP),在面向对象的世界里,一切皆为对象。面向对象是一种解决问题的一种思想,主要依靠对象之间的交互完成一件事。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。



总共有四个对象:人、衣服、洗衣机。
整个洗衣服的过程就变成了人设置洗衣机,让洗衣机洗衣服的过程。
一面向对象方式来进行处理,就不关注洗衣服的过程,具体是怎麽洗衣服我们并不关注,我们只需要对洗衣机进行交互即可。通过对象间的交互来完成任务。
【注意】面向对象和面向过程是解决问题的两种思路,并没有好坏之分。
面向对象设计的重点是对象。而对象是生活中的实体,如洗衣服,房子。
***类是用来对一个实体(对象)来进行描述的,***主要描述该对象的具体属性和功能。描述之后计算机即可识别和使用。
比如:类:手机
属性:品牌,颜色,系统…
功能:打电话,看视频,听音乐…
接下来让我们在Java中来定义。
在Java中定义类时需要用到 class 关键字,格式如下:
class className {
//成员属性
//方法
}
class 为定义类时的关键字,className 为类的名字,{}内为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称为类的成员属性或者成员变量。方法主要说明类的功能,称为类的成员方法。
这里我们定义一个狗的类。
//关于狗的类
class Dog {
//成员属性 成员变量
public String name;
public int age;
//成员方法
public void eat() {
System.out.println("吃骨头!");
}
public void run() {
System.out.println("用四条腿奔跑!");
}
}
【注意事项】
//定义一个学生类
class Student {
//成员属性 成员变量
public String name;
public int age;
public int achievement;
//成员方法
public void DoHomeork() {
System.out.println("写作业!");
}
public void play() {
System.out.println("去玩耍!");
}
}
【注意事项】
定义了一个类,就相当于在计算机中定义了一种新的类型,与 int, double 类似,只不过 int 和 double 是Java 语言自带的内置类型,而类是用户自定义了一种新的类型。比如上述的:DOG 和 Student 类。
用类创建对象的过程,称为类的实例化。在Java中采取 new 关键字,配合类名来实例化的对象。
//狗
//实例化对象
class Dog {
public String name;
public int age;
public void wangwang() {
System.out.println("汪汪叫!");
}
public void run() {
System.out.println("用四条腿奔跑!");
}
}
public class test {
public static void main(String[] args) {
Dog dog1 = new Dog();//通过new实例化对象
dog1.name = "汪汪队";
dog1.age = 1;
dog1.run();
dog1.wangwang();
//再实例化一个对象
Dog dog2 = new Dog();
dog2.name = "哮天犬";
dog2.age = 100;
dog2.run();
dog2.wangwang();
}
}

【注意事项】

//this 应用
//为什么要有this引用
class Date {
public int year;
public int month;
public int day;
public void setDate(int y, int m, int d) {
year = y;
month = m;
day = d;
}
public void printDate() {
System.out.println(year + "." + month + "." + day);
}
}
public class test {
public static void main(String[] args) {
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
d1.setDate(2022, 11, 17);
d2.setDate(2011, 11, 12);
d3.setDate(2001, 1, 30);
d1.printDate();
d2.printDate();
d3.printDate();
}
}

以上代码定义了一个日期类, 同时main方法中创建了三个对象,通过对Date类中的成员方法我们可以对对象进行初始化和打印。但是有两个疑问。
1. 参数名与成员变量相同时会发生什么?
public void setDate(int year, int month, int day) {
year = year;
month = month;
day = day;
}
函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?这样我们又能否进行初始化?
2. 三个对象都在调用setDate和printDate函数,但是这两个函数中并没有任何有关对象的说明,setDate和printDate函数如何知道对象的数据呢?

接下来让我们揭开this神秘的面纱。
***this应用指向当前对象,在成员方法中对成员变量的操作,都是通过引用去访问。***只不过所有的操作对用户都是透明的,即用户不需要自己来传递,编译器会帮你完成。

在实际的操作过程中编译器都会加上这样的参数,以便识别不同的对象。
【注意】this引用的时调用成员方法的对象。
构造方法(也称构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期只能调用一次。
/构造方法
//概念
class Date {
public int year;
public int month;
public int day;
//构造方法
//名字要与类名熊,没有放回值,void也不行
//一般情况下使用public修饰
//创建对象时由编译器自动调用,并且在对象的生命周期内只能调用一次。
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date带参数的构造别调用了一次");
}
public void printDate() {
System.out.println(year + "-" + month + "-" + day);
}
}
public class test {
public static void main(String[] args) {
//此处创建对象时,构造方法自动被调用
Date d = new Date(2022, 11, 17);
d.printDate();
}
}
【注意】构造方法的作用是对对象中的成员进行初始化,并不负责开辟空间。
//this调用其他的构造方法
class Date {
public int year;
public int month;
public int day;
public Date() {
//这里的this调用了另一个带参的构造方法
//this(...)必须放在构造方法的第一行
this(2000, 1, 1);
System.out.println("Date不带参数的构造方法被调用了一次");
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date带参数的构造别调用了一次");
}
public void printDate() {
System.out.println(year + "-" + month + "-" + day);
}
}
public class test {
public static void main(String[] args) {
//此处创建对象时,构造方法自动被调用
Date d = new Date();
d.printDate();
}
}

在上文中提出的第二个问题:为什么局部变量在使用时必须初始化,而成员变量不需要呢?
//默认初始化
class Date {
public int year;
public int month;
public int day;
public void printDate() {
System.out.println(year + "-" + month + "-" + day);
}
}
public class test {
public static void main(String[] args) {
//此处创建对象时,构造方法自动被调用
Date d = new Date();
d.printDate();
}
}

要搞清楚这个过程,就要知道new关键字背后所发生的一些事情。
Date d = new Date(2021,6,9);
在程序层面只是一条简单的语句,但是在JVM层面需要做好多的事情:
| 数据类型 | 默认值 |
|---|---|
| byte\short\int | 0 |
| long | 0L |
| float | 0.0f |
| double | 0.0 |
| char | ‘\u0000’ |
| boolean | false |
| reference | null |
在声明成员变量时,直接给出初始值。
//就地初始化
class Date {
public int year = 2000;
public int month = 1;
public int day = 1;
public void printDate() {
System.out.println(year + "-" + month + "-" + day);
}
}
public class test {
public static void main(String[] args) {
//此处创建对象时,构造方法自动被调用
Date d = new Date();
d.printDate();
}
}

【注意】代码编译完成后,编译器会将所有给成员初始化的这些语句,添加到构造函数中。(意思如下)

面向对象程序的三大特性:封装、继承、多态。
何为封装?简单的说就是套壳屏蔽细节。
比如:我们使用洗衣机的时候,我们只需要下达命令让其执行,我们不需要知道洗衣机工作原理和方法。
使用电脑进行办公时,我们只需下达命令让其操作,我们不需要关注电脑是如何实现这些功能的。
封装:将数据和操作数据的方法进行有机的结合,隐蔽对象的属性和实现细节,仅对外公开接口来和对象进行交互。
Java中主要通过类的访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认识,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:
| 范围 | private | default | protected | public |
|---|---|---|---|---|
| 同一包中的同一类 | √ | √ | √ | √ |
| 同一包中的不同类 | √ | √ | √ | |
| 不同包中的子类 | √ | √ | ||
| 不同包中的非子类 | √ |
比如:
public:可以理解为一个人的外貌特征,谁都能看到;
default:对于自己家族中(同一个包)不是什么秘密,对于其他人来说就是隐私了。
private:只有自己知道,其他人不知道。
【说明】
//访问限定符
class Computer {
private String cpu;
private String memory;
public String screen;
String brand;
public Computer(String cpu, String memory, String screen, String brand) {
this.brand = brand;
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
}
public void Surflnternet() {
System.out.println("上网!");
}
}
public class test {
public static void main(String[] args) {
Computer p = new Computer("hw", "i7","8G","13*14");
System.out.println(p.cpu);//这里cpu只能在自己的类中被访问,失败
System.out.println(p.screen);//可以被其他类访问,成功
System.out.println(p.brand);//可以在同一包被访问,成功
}
}
在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起形成一个组,称为软件包。比如:我们为了更好的管理电脑中的音乐,我们可以将中文歌放在一个文件夹里,把英文歌放在另一个文件夹里,把日语歌放在另一个文件夹里。每一个文件夹就相当于一个包。

在Java中也引入了包。包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包即可。
Java中已经提供了很多现成的类供我们使用。例如Date类:可以使用java.util.Date导入java.util这个包中的Date类。
\
//导入包中的类
public class test {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
//得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
这种写法有些麻烦,可以***使用import语句导入包。
import java.util.Date;
//导入包中的类
public class test {
public static void main(String[] args) {
//java.util.Date date = new java.util.Date();
Date date = new Date();
//得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
但是我们更建议显示的指定要导入的类名。否则还是容易出现冲突的情况(在不同的包中,有相同名称的类名会发生冲突)。
【基本规则】





Computer类位于com.baidu.demo1包中,TestComputer位置com.baidu.demo2包中
package com.baidu.demo1;
public class Computer {
String brand;
private String cpu;
private String memory;
public String screen;
public Computer(String brand, String cpu, String memory, String screen) {
this.brand = brand;
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
}
public void Surflnternet() {
System.out.println("网上冲浪~~~~");
}
}
package com.baidu.demo2;
import com.baidu.demo1.Computer;
public class TestComputer {
public static void main(String[] args) {
Computer p = new Computer("hw", "i7", "8G", "13*14");
System.out.println(p.screen);
//System.out.println(p.cpu); //错误,cpu是私有的,不允许被其他类访问
//System.out.println(p.brand);//错误,brand是默认的,不允许被其他包中的类访问
}
}
使用前文中介绍的学生类实例化三个对象s1, s2, s3, 每个对象都有自己的名字,年龄,成绩等成员信息,这些信息就是对不同学生的描述,但是这几个学生都有一个相同的特性,我们将如何表示呢?
在Java中,被static修饰的成员,被称为静态成员,也称为类成员,其不属于某一个具体的对象,而是所有对象共享的。
static修饰的成员变量,称为静态成员变量。
【静态成员变量特征】
//static修饰的成员变量
class Student {
//成员属性 成员变量
public String name;
public int age;
public int achievement;
public static String school = "大肥羊学校";
public Student(String name, int age, int achievement) {
this.name = name;
this.age = age;
this.achievement = achievement;
}
//成员方法
public void DoHomework() {
System.out.println("写作业!");
}
public void play() {
System.out.println("去玩耍!");
}
}
public class test {
public static void main(String[] args) {
Student s1 = new Student("喜羊羊",10, 99);
Student s2 = new Student("懒洋洋",9, 60);
Student s3 = new Student("美羊羊",10, 83);
//通过对象访问静态成员变量
System.out.println(s1.school);
System.out.println(s2.school);
System.out.println(s3.school);
//通过类访问静态成员变量
System.out.println(Student.school);
}
}
一般类中的数据成员都设置为private,而成员方法设置public,那样设置之后,Student类中school属性又如何在类外访问呢?

答案是我们可以通过方法方法来在类外访问和修改相关变量,实例如下:
//static修饰的成员变量
//成员变量使用private修饰,我们如何访问成员变量
class Student {
//成员属性 成员变量
private String name;
private int age;
private int achievement;
private static String school = "大肥羊学校";
public Student(String name, int age, int achievement) {
this.name = name;
this.age = age;
this.achievement = achievement;
}
//成员方法
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getAchievement() {
return achievement;
}
public static String getSchool() {
return school;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setAchievement(int achievement) {
this.achievement = achievement;
}
public static void setSchool(String school) {
Student.school = school;
}
public void DoHomework() {
System.out.println("写作业!");
}
public void play() {
System.out.println("去玩耍!");
}
}
public class test {
public static void main(String[] args) {
Student s1 = new Student("喜羊羊",10, 99);
Student s2 = new Student("懒洋洋",9, 60);
Student s3 = new Student("美羊羊",10, 83);
//访问成员变量
System.out.println(s1.getName());
System.out.println(s2.getAge());
System.out.println(s3.getAchievement());
//访问静态成员变量
System.out.println(Student.getSchool());
}
}
Java中,***被static修饰的成员方法称为静态成员方法,是类的方法。***静态成员变量一般通过静态成员方法来访问(如上述的getSchool()).
【静态方法特征】
注意:今天太成员变量一般不会放在构造方法中来初始化,构造方法初始化的是与对象相关的实例属性。
静态成员变量的初始化分为来个两种:就地初始化和静态代码块初始化
private static String school = "大肥羊学校”;
2.静态代码初始化
什么是静态代码块呢?继续往下看:)~~
***使用{ }定义的一段代码称为代码块。***根据代码块定义的位置以及关键词,又可以分为一下四种:
定义在方法中的代码块。(非常少见)
//普通代码块
public class test {
public static void main(String[] args) {
{
//此部分为普通代码块
int x = 10;
System.out.println(x);
}
int x = 30;
System.out.println(x);
}
}

构造块:定义在类中的代码块(不加修饰词),也叫实例代码块。构造代码块一般用于初始化实例成员变量。(初始化成员变量的另一种方法)
//构造代码块
class Student {
private String name;
private int age;
private int achievement;
private static String school = "大肥羊学校";
//构造代码块 实例代码块
{
name = "未知";
age = 10;
achievement = 100;
}
public Student() {
}
public Student(String name, int age, int achievement) {
this.name = name;
this.age = age;
this.achievement = achievement;
}
public void DoHomework() {
System.out.println("写作业!");
}
public void play() {
System.out.println("去玩耍!");
}
public void show() {
System.out.println(name + " " +age + " " +achievement);
}
}
public class test {
public static void main(String[] args) {
Student s = new Student();
s.show();
}
}

使用static定义的代码块被称为静态代码块。一般用于初始化静态成员变量
//静态代码块
class Student {
private String name;
private int age;
private int achievement;
private static String school;
//静态代码块
static {
school = "大肥羊学校";
System.out.println(school);
}
//构造代码块 实例代码块
{
name = "未知";
age = 10;
achievement = 100;
}
public Student() {
}
public Student(String name, int age, int achievement) {
this.name = name;
this.age = age;
this.achievement = achievement;
}
public void DoHomework() {
System.out.println("写作业!");
}
public void play() {
System.out.println("去玩耍!");
}
public void show() {
System.out.println(name + " " +age + " " +achievement);
}
}
public class test {
public static void main(String[] args) {
Student s = new Student();
s.show();
}
}
【注意事项】
我们要打印对象的成员变量我们应当怎么做呢?
//toString
class Person {
String name;
String gender;
int age;
public Person(String name, String gender, int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
// public String toString() {
// return "[" + name + "," + gender + "," + age + "]";
// }
}
public class test {
public static void main(String[] args) {
Person person = new Person("Jim","男", 18);
System.out.println(person.toString());
}
}

Person类,@分割,后面的时十六进制地址。
如果我们要打印对象的成员属性,我们可以重写toString()这个方法。
