内容目录
java
面向对象和面向过程的思想对比 :
面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的
面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能
面向对象概述
面向对象思想,将所有预处理的问题抽象为对象,通过了解这些对象具有哪些相应的属性以及展示这些对象的行为,以解决这些对象面临的一些实际问题。在程序开发中引入面向对象设计的概念,其实质上就是对现实世界中的对象进行建模操作。对象
通过探讨对象的属性和观察对象的行为来了解对象。
类
对象就是符合某个类的定义所产生出来的实例。更为恰当的描述是,类是世间事物的抽象称呼,而对象则是这个事物相对应的实体。
如果面临实际问题,通常需要实例化类对象来解决。
类是封装对象的属性和行为的载体,反过来说,具有相同属性和行为的一类实体被称为类。例如,鸟类封装了所有鸟的共同属性和应具有的行为,定义完鸟类之后,可以根据这个类抽象出一个实体对象,最后通过实体对象来解决相关的实际问题。
在 Java 语言中,类中对象的行为是以 方法 的形式定义的,对象的属性是以 成员变量 的形式定义的,所以类包括对象的属性和方法。封装
封装是面向对象编程的核心思想。将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。
采用封装的思想保证了类内部数据结构的完整性,应用该类的用户不能轻易地直接操作此数据结构,只能执行类允许公开的数据。这样就避免了外部操作对内部数据的影响,提高了程序的可维护性。
继承
一个类处于继承体系中,它既可以是其他类的父类,为其他类提供属性和行为,也可以是其他类的子类,继承父类的属性和方法,如三角形既是图形类的子类也是等边三角形的父类。
多态
将父类对象应用于子类的特征就是多态以图形类来说明多态,每个图形都拥有绘制自己的能力,这个能力可以看作是该类具有的行为,如果将子类的对象统一看作是父类的实例对象,这样当绘制图形时,简单地调用父类也就是图形类绘制图形的方法即可绘制任何图形,这就是多态最基本的思想。
多态性允许以统一的风格编写程序,以处理种类繁多的已存在的类及相关类。该统一风格可以由父类来实现,根据父类统一风格的处理,可以实例化子类的对象。由于整个事件的处理都只依赖于父类的方法,所以日后只要维护和调整父类的方法即可,这样就降低了维护的难度,节省了时间。
抽象类与接口
多态的实现并不依赖于具体类,而是依赖于抽象类和接口。 抽象类不能实例化对象。在多态的机制中,比抽象类更方便的方式是将抽象类定义为接口。由抽象方法组成的集合就是接口。
类和对象
类和对象的关系
客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。 1)类 类的理解- 类是对现实生活中一类具有共同属性和行为的事物的抽象
- 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合
- 简单理解:类就是对现实事物的一种描述
- 属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)
- 行为:指事物能执行的操作,例如:手机事物(打电话,发短信)
- 类:类是对现实生活中一类具有共同属性和行为的事物的抽象
- 对象:是能够看得到摸的着的真实存在的实体
- 简单理解: 类是对事物的一种描述,对象则为具体存在的事物
类的定义
类的组成是由属性和行为两部分组成- 属性:在类中通过成员变量来体现(类中方法外的变量)
- 行为:在类中通过成员方法来体现(和前面的方法相比去掉 static 关键字即可)
类的定义步骤:
① 定义类 ② 编写类的成员变量 ③ 编写类的成员方法public class 类名 {
// 成员变量
变量1的数据类型 变量1;
变量2的数据类型 变量2;
…
// 成员方法
方法1;
方法2;
}
示例代码:
public class Student {
// 属性 : 姓名, 年龄
// 成员变量: 跟之前定义变量的格式一样, 只不过位置发生了改变, 类中方法外
String name;
int age;
// 行为 : 学习
// 成员方法: 跟之前定义方法的格式一样, 只不过去掉了static关键字.
public void study(){
System.out.println("学习");
}
}
对象的创建和使用
创建对象的格式:类名 对象名 = new 类名(); 调用成员的格式:- 对象名.成员变量
- 对象名.成员方法();
package com.itheima.object1;
public class TestStudent {
/*
创建对象的格式:
类名 对象名 = new 类名();
调用成员变量的格式:
对象名.变量名
调用成员方法的格式:
对象名.方法名();
*/
public static void main(String[] args) {
// 类名 对象名 = new 类名();
Student stu = new Student();
// 对象名.变量名
// 默认初始化值
System.out.println(stu.name); // null
System.out.println(stu.age); // 0
stu.name = "张三";
stu.age = 23;
System.out.println(stu.name); // 张三
System.out.println(stu.age); // 23
// 对象名.方法名();
stu.study();
// com.itheima.object1.Student@b4c966a
// 全类名(包名 + 类名)
System.out.println(stu);
}
}
学生对象-练习
需求:首先定义一个学生类,然后定义一个学生测试类,在学生测试类中通过对象完成成员变量和成员方法的使用 分析:- 成员变量:姓名,年龄…
- 成员方法:学习,做作业…
public class Student {
//成员变量
String name;
int age;
//成员方法
public void study() {
System.out.println("好好学习,天天向上");
}
public void doHomework() {
System.out.println("键盘敲烂,月薪过万");
}
}
/*
学生测试类
*/
public class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
//使用对象
System.out.println(s.name + "," + s.age);
s.name = "林青霞";
s.age = 30;
System.out.println(s.name + "," + s.age);
s.study();
s.doHomework();
}
}
类
类的主方法
public static void main(String[] args) {
// 方法体
}
在主方法的定义中可以看到其具有以下特性:
- 主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
- 主方法没有返回值。
- 主方法的形参为数组。其中
args[0]~args[n]
分别代表程序的第一个参数到第 n 个参数,可以使用args.length
获取参数的个数。
成员变量
在 Java 中对象的属性也称为成员变量。成员变量可以是任意类型,整个类中均是成员变量作用范围。
成员变量的类型可以设置为 Java 中合法的数据类型,其实成员变量就是普通的变量,可以为它设置初始值,也可以不设置初始值。如果不设置初始值,则会有默认值。
成员方法
定义成员方法的语法格式如下:
权限修饰符 返回值类型 方法名(参数类型 参数名) {
... // 方法体
return 返回值;
}
一个成员方法可以有参数,这个参数可以是对象,也可以是基本数据类型的变量,同时成员方法有返回值和不返回任何值的选择,如果方法需要返回值,可以在方法体中使用 return 关键字,使用这个关键字后,方法的执行将被终止。
Java 中的成员方法无返回值,可以使用 void 关键字表示。
成员方法的返回值可以是计算结果,也可以是其他想要的数值和对象,返回值类型要与方法返回的值类型一致。
在成员方法中可以调用其他成员方法和类成员变量,
说明:
如果一个方法中含有与成员变量同名的局部变量,则方法中对这个变量的访问以局部变量进行。
类成员变量和成员方法也可以统称为类成员。
权限修饰符
如果一个类的成员变量或成员方法被修饰为 private,则该成员变量只能在本类中被使用,在子类中是不可见的,并且对其他包的类也是不可见的。
如果将类的成员变量和成员方法的访问权限设置为 public,那么除了可以在本类使用这些数据之外,还可以在子类和其他包的类中使用。
如果一个类的访问权限被设置为 private,这个类将隐藏其内的所有数据,以免用户直接访问它。
如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为 public 访问权限。
如果一个类使用 protected 修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和成员方法。
这么看来,public 和 protected 修饰的类可以由子类访问,如果子类和父类不在同一包中,那么只有修饰符为 public 的类可以被子类进行访问。如果父类不允许通过继承产生的子类访问它的成员变量,那么必须使用 private 声明父类的这个成员变量。
注意:
当声明类时不使用 public、protected 和 private 修饰符设置类的权限,则这个类预设为包存取范围,即只有一个包中的类可以调用这个类的成员变量或成员方法。
局部变量
局部变量是在方法被执行时创建,在方法执行结束时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。局部变量的有效范围
注意:
在作用范围外使用局部变量是一个常见的错误,因为在作用范围外没有声明局部变量的代码。
this 关键字
this 可以调用成员变量和成员方法,但 Java 语言中最常规的调用方式是使用"对象.成员变量
"或"对象.成员方法
"进行调用。
思考:既然 this 关键字和对象都可以调用成员变量和成员方法,那么 this 关键字与对象之间具有怎样的关系呢?
事实上,this 引用的就是本类的一个对象。在局部变量或方法参数覆盖了成员变量时,如上面代码的情况,就要添加 this 关键字明确引用的是类成员还是局部变量或方法参数。
this 除了可以调用成员变量或成员方法之外,还可以作为方法的返回值。
示例代码:
public Book getBook() {
return this; // 返回 Book 类引用
}
在 getBook() 方法中,方法的返回值为 Book 类,所以方法体中使用 return this 这种形式将 Book 类的对象进行返回。
封装
封装思想
1、封装概述 是面向对象三大特征之一(封装,继承,多态), 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的。对象代表什么,就得封装对应的数据,并提供数据对应的行为。
2、 封装原则 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问,成员变量 private,提供对应的<font style="color:rgb(38, 38, 38);">getXxx() / setXxx()</font>
方法
3、
封装好处
通过方法来控制成员变量的操作,提高了代码的安全性 把代码用方法进行封装,提高了代码的复用性。
private 关键字
概述:private 是一个修饰符,可以用来修饰成员(成员变量,成员方法)特点:被 private 修饰的成员,只能在本类进行访问,针对 private 修饰的成员变量,如果需要被其他类使用,提供相应的操作:
- 提供"get 变量名()"方法,用于获取成员变量的值,方法用 public 修饰
- 提供"set 变量名(参数)"方法,用于设置成员变量的值,方法用 public 修饰
示例代码:
/*
学生类
*/
class Student {
//成员变量
String name;
private int age;
//提供get/set方法
public void setAge(int a) {
if(a<0 || a>120) {
System.out.println("你给的年龄有误");
} else {
age = a;
}
}
public int getAge() {
return age;
}
//成员方法
public void show() {
System.out.println(name + "," + age);
}
}
/*
学生测试类
*/
public class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
//给成员变量赋值
s.name = "林青霞";
s.setAge(30);
//调用show方法
s.show();
}
}
private 关键字的使用
需求:- 定义标准的学生类,要求 name 和 age 使用 private 修饰
- 并提供 set 和 get 方法以及便于显示数据的 show 方法
- 测试类中创建对象并使用,最终控制台输出 林青霞,30
示例代码:
/*
学生类
*/
class Student {
//成员变量
private String name;
private int age;
//get/set方法
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void setAge(int a) {
age = a;
}
public int getAge() {
return age;
}
public void show() {
System.out.println(name + "," + age);
}
}
/*
学生测试类
*/
public class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
//使用set方法给成员变量赋值
s.setName("林青霞");
s.setAge(30);
s.show();
//使用get方法获取成员变量的值
System.out.println(s.getName() + "---" + s.getAge());
System.out.println(s.getName() + "," + s.getAge());
}
}
this 关键字
this 修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题)- 方法的形参如果与成员变量同名,不带 this 修饰的变量指的是形参,而不是成员变量
- 方法的形参没有与成员变量同名,不带 this 修饰的变量指的是成员变量
示例代码:
public class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void show() {
System.out.println(name + "," + age);
}
}
this 内存原理
注意:this 代表当前调用方法的引用,哪个对象调用的方法,this 就代表哪一个对象。类的构造方法
构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。
构造方法的特点如下:
- 构造方法没有返回值。
- 构造方法的名称要与本类的名称相同。
构造方法概述
构造方法是一种特殊的方法。 作用:创建对象<font style="color:rgb(38, 38, 38);">Student stu = </font>**<font style="color:rgb(38, 38, 38);">new Student();</font>**
功能:主要是完成对象数据的初始化 。
格式:
public class 类名{
}
修饰符 类名(参数) {
}
// 示例:
public book() {
... // 构造方法体
}
public:构造方法修饰符。
book:构造方法的名称。
在构造方法中可以为成员变量赋值,这样当实例化一个本类的对象时,相应的成员变量也将被初始化。
如果类中没有明确定义构造方法,编译器会自动创建一个不带参数的默认构造方法。
格式注意:
- 方法名与类名相同,大小写也要一致
- 没有返回值类型,不需要使用 void 关键字进行修饰
- 没有返回值(不能由 retrun 带回结果数据)
执行时机:
- 创建对象的时候调用,每创建一次对象,就会执行一次构造方法
- 不能手动调用构造方法
class Student {
private String name;
private int age;
//构造方法
public Student() {
System.out.println("无参构造方法");
}
public void show() {
System.out.println(name + "," + age);
}
}
/*
测试类
*/
public class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
s.show();
}
}
构造方法的作用
用于给对象的数据(属性)进行初始化package com.itheima.constructor;
public class Student {
/*
格式:
1. 方法名需要跟类名相同, 大小写也要一致
2. 没有返回值类型, 连 void 都没有
3. 没有具体的返回值(不能由 return 带回具体的结果)
*/
private String name;
private int age;
// 1. 如果一个类中没有编写任何构造方法, 系统将会提供一个默认的无参数构造方法
public Student(){}
// 2. 如果手动编写了构造方法, 系统就不会再提供默认的无参数构造方法了
public Student(String name, int age){
this.name = name;
this.age = age;
System.out.println("我是Student类的构造方法");
}
public void show(){
System.out.println(name + "..." + age);
}
}
package com.itheima.constructor;
public class TestStudent {
public static void main(String[] args) {
Student stu1 = new Student("张三",23);
stu1.show();
Student stu2 = new Student();
}
}
构造方法的注意事项
1)构造方法的创建 如果没有定义构造方法,系统将给出一个默认的无参数构造方法;如果定义了构造方法,系统将不再提供默认的构造方法。2)构造方法的重载
如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法。 3)推荐的使用方式 无论是否使用,都要手工书写无参数构造方法、和带参数构造方法。 4)重要功能 可以使用带参构造,为成员变量进行初始化。标准类制作(标准的 **javabean 类**代码编写和使用)
① 类名需要见名知意 ② 成员变量使用 private 修饰 ③ 提供至少两个构造方法- 无参构造方法
- 带全部参数的构造方法
<font style="color:rgb(38, 38, 38);">setXxx()</font>
和
<font style="color:rgb(38, 38, 38);">getXxx()</font>
)
⑤ 如果还有其他行为,也需要写上
示例代码:
/*
JavaBean 类: 封装数据
*/
public class Student {
// 成员变量
private String name;
private int age;
// 构造方法
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 成员方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println(name + "..." + age);
}
}
/*
创建对象并为其成员变量赋值的两种方式
1: 无参构造方法创建对象后使用 setXxx() 赋值
2: 使用带参构造方法直接创建带有属性值的对象
*/
public class TestStudent {
public static void main(String[] args) {
// 1. 无参数构造方法创建对象, 通过setXxx方法给成员变量进行赋值
Student stu1 = new Student();
stu1.setName("张三");
stu1.setAge(23);
stu1.show();
// 2. 通过带参数构造方法, 直接给属性进行赋值
Student stu2 = new Student("李四",24);
stu2.show();
}
}
练习
public class User {
//1.私有化全部的成员变量
//2.空参构造
//3.带全部参数的构造
//4.针对于每一个私有化的成员变量都要提供其对应的get和set方法
//5.如果当前事物还有其他行为,那么也要写出来,比如学生的吃饭,睡觉等行为
private String username;//用户名
private String password;//密码
private String email;//邮箱
private char gender;//性别
private int age;//年龄
//空参构造方法
public User() {
}
//带全部参数的构造
public User(String username, String password, String email, char gender, int age) {
this.username = username;
this.password = password;
this.email = email;
this.gender = gender;
this.age = age;
}
//get和set
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat(){
System.out.println(username + "在吃饭");
}
}
public class Test {
public static void main(String[] args) {
//写一个标准的javabean类
//咱们在课后只要能把这个标准的javabean能自己写出来,那么就表示今天的知识点就ok了
//利用空参构造创建对象
User u1 = new User();
//如果利用空参创建对象,还想赋值只能用set方法赋值
u1.setUsername("zhangsan");
u1.setPassword("1234qwer");
u1.setEmail("itheima@itcast.cn");
u1.setGender('男');
u1.setAge(23);
//获取属性的值并打印
System.out.println(u1.getUsername() + ", " + u1.getPassword()
+ ", " + u1.getEmail() + ", " + u1.getGender() + ", " + u1.getAge());
u1.eat();
System.out.println("=============================");
//简单的办法
//利用带全部参数的构造来创建对象
//快捷键:ctrl + p
User u2 = new User("lisi","12345678","lisi@itcast.cn",'女',24);
System.out.println(u2.getUsername() + ", " + u2.getPassword()
+ ", " + u2.getEmail() + ", " + u2.getGender() + ", " + u2.getAge());
u2.eat();
}
}
静态变量和静态方法
static 关键字
静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和"."运算符调用静态成员。
语法如下:
类名.静态类成员
注意:
虽然静态成员也可以使用"对象.静态成员
"的形式进行调用,但通常不建议用这样的形式,因为这样容易混淆静态成员和非静态成员。
静态数据与静态方法的作用通常是为了提供共享数据或方法,如数学计算公式等,以 static 声明并实现,这样当需要使用时,直接使用类名调用这些静态成员即可。
尽管使用这种方式调用静态成员比较方便,但静态成员同样遵循着 public、private 和 protected 修饰符的约束。
在静态方法中不可以使用 this 关键字。
在静态方法中不可以直接调用非静态方法。
在 Java 中规定不能将方法体内的局部变量声明为 static 的。示例代码就是错误的:
public class example {
public void method() {
static int i = 0;
}
}
如果在执行类时,希望先执行类的初始化动作,可以使用 static 定义一个静态区域。例如:
public class example {
static {
// some
}
}
当这段代码被执行时,首先执行 static 块中的程序,并且只会执行一次。
**成员变量和局部变量**
成员变量和局部变量的区别
类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)内存中位置不同:成员变量(堆内存)局部变量(栈内存)生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,随着方法的调用完毕而消失)初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)对象
对象的创建
准确地说,可以在 Java 中使用 new 关键字调用构造方法创建对象。
语法格式:<font style="color:rgb(38, 38, 38);">类名 对象名 = new 类名();</font>
// 类名 对象名 = new 类名();
Student student = new Student();
student 对象被创建出来时,就是一个对象的引用,这个引用在内存中为对象分配了存储空间,可以在构造方法中初始化成员变量,当创建对象时,自动调用构造方法。也就是说,在 Java 语言中初始化与创建是被捆绑在一起的。
每个对象都是相互独立的,在内存中占据独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由 Java 虚拟机自带的垃圾回收机制处理,不能再被使用。
访问对象的属性和行为
对象的属性和行为在类中是通过类成员变量和成员方法的形式来表示的,所以当对象获取类成员时,也相应地获取了对象的属性和行为。
- 对象名.成员变量
- 对象名.成员方法();
对象的引用
例如:一个 Book 类的引用可以使用以下代码:
Book book;
通常一个引用不一定需要有一个对象相关联。引用与对象相关联的语法如下:
Book book = new Book();
Book:类名。
book:对象。
new:创建对象关键字
注意:
引用只是存放一个对象的内存地址,并非存放一个对象。严格地说,引用和对象是不同的,但是可以将这种区别忽略,如可以简单地说 book 是 Book 类的一个对象,而事实上应该是 book 包含 Book 对象的一个引用。
对象的比较(== 和 equals)
equals()
方法是 String 类中的方法,它用于比较两个对象引用所指的内容是否相等;
"`=="运算符比较的是两个对象引用的地址是否相等。
对象的销毁
什么对象会被 Java 虚拟机视为"垃圾"?
主要包括以下两种情况:
- 对象引用超过其作用范围,这个对象将被视为垃圾。
- 示例:
- 示例:
- 将对象赋值为 null。
- 示例:
- 示例:
注意:垃圾回收器只能回收那些由 new 关键字创建的对象。
某些对象不是通过 new 关键字在内存中获取存储空间的,这种对象无法被垃圾回收机制所识别。
在 Java 中提供了一个finalize()
方法,这个方法是 Object 类的方法,它被声明为 protected,用户可以在自己的类中定义这个方法。
如果用户在类中定义了finalize()
方法,在垃圾回收时会首先调用该方法,在下一次垃圾回收动作发生时,才真正回收被对象占用的内存。
需要注意的是,垃圾回收或finalize()
方法并不保证一定会发生。如果 Java 虚拟机内存损耗待尽,它将不会执行垃圾回收处理。
由于垃圾回收不受人为控制,具体执行时间也不确定,所以finalize()
方法也就无法执行。
因此,Java 提供了System.gc()
方法来强制启动垃圾回收器,这与给 120 打电话通知医院来救护病人的道理一样,主动告知垃圾回收器来进行清理。
对象内存图
单个对象内存图
成员变量使用过程多个对象内存图
成员变量使用过程总结:
多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,成员方法多个对象共用的一份。多个对象指向相同内存图
总结:
当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的) 只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。