1.面向对象的初步认知
1.2 面向对象与面向过程
洗衣机:
学完C之后,我们看到这个流程图,可能就不想编代码了,流程太复杂,代码维护和拓展成本太高
传统的方式: 注重的是洗衣服的过程 ,少了一个环节可能都不行。放到现实中看,洗衣服的过程其实很少:人把衣服放到洗衣机,倒入洗衣粉,启动洗衣机,甩干,整个过程只有人,洗衣机。衣服,洗衣粉四个对象,人不需要关心洗衣机的工作
以面向对象方式来进行处理,就不关注洗衣服的过程,用户不用去关心,只需要将衣服放进洗衣机,倒入洗衣粉,启动开关即可,通过对象之间的交互来完成的。
注意:面向过程和面向对象并不是一门语言,而是解决问题的方法,没有那个好坏之分,都有其专门的应用场景。我们不可能说某件事有最好的办法,但一定有更好的
2. 类定义和使用
面相对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机。但是洗衣机计算机并不认识,需要开发人员告诉给计算机一些基本概念。
2.1 简单认识类
类是用来对一个实体 ( 对象 ) 来进行描述的 ,主要描述该实体 ( 对象 ) 具有哪些属性 ( 外观尺寸等 ) ,哪些功能 ( 用来干啥)比如:洗衣机,它是一个品牌,在Java中可以将其看成是一个类别。在类中要描述它的属性和功能。
2.2 类的定义格式
// 创建类
class ClassName{
field; // 字段(属性) 或者 成员变量
method; // 行为 或者 成员方法
}
别急,看不懂不要紧,下面来解释
class为定义类的关键字,ClassName为类的名字,{}中为类的主体。类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
class WashMachine{
//属性
public String brand; // 品牌
public String type; // 型号
public double weight; // 重量
public String color; // 颜色
//功能
public void washClothes(){ // 洗衣服
System.out.println("洗衣功能");
}
public void dryClothes(){ // 脱水
System.out.println("脱水功能");
}
public void setTime(){ // 定时
System.out.println("定时功能");
}
}
1. 一般一个文件当中只定义一个类2. public 修饰的类必须要和文件名相同3. main 方法所在的类一般要使用 public 修饰
3. 类的实例化
在java中采用new关键字,配合类名来实例化对象。
![](https://i-blog.csdnimg.cn/direct/2c40c4090e254fcab2bd4441ff67b292.png)
import java.util.Arrays;
class Main {
public static void main(String[] args) {
PetDog dogs = new PetDog(); //通过new实例化对象
dogs.name = "阿黄";
dogs.color = "黑黄";
dogs.bark();
dogs.wag();
}
}
class PetDog {
public String name;
public String color;
public int barks;
public int wag;
public void bark() {
System.out.println("狗叫!!!");
}
public void wag () {
System.out.println("神狗扫尾!!!");
}
}
//运行结果
狗叫!!!
神狗扫尾!!!
使用 . 来访问对象中的属性和方法 .如上述的dogs.wag()同一个类可以创建多个实例 .public 修饰的类必须要和文件名相同
3.1 类和对象的说明
类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,而按照设计图建造的房子叫做实例。
4. this引用
this 引用指向当前对象 ,在成员方法中所有成员变量的操作,都是通过该 引用去访问 。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
public void setDay ( int year , int month , int day ){year = year ;month = month ;day = day ;}
class Date {
public int year;
public int month;
public int day;
public void setDay(int y, int m, int d){
year = y;
month = m;
day = d;
}
public void printDate(){
System.out.println(year + "/" + month + "/" + day);
}
public static void main(String[] args) {
// 构造三个日期类型的对象 d1 d2 d3
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
// 对d1,d2,d3的日期设置
d1.setDay(2020,9,15);
d2.setDay(2020,9,16);
d3.setDay(2020,9,17);
// 打印日期中的内容
d1.printDate();
d2.printDate();
d3.printDate();
}
改正后的代码,看起来更美观
‘注意:this引用的是调用成员方法的对象。
this可以理解为对象的一个隐藏属性,this可以用来区分当前类的属性和局部变量
public class Date {
public int year;
public int month;
public int day;
public void setDay(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
public void printDate(){
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
}
1. this 的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型2. this 只能在 " 成员方法 " 中使用3. 在 " 成员方法 " 中, this 只能引用当前对象,不能再引用其他对象
5. 对象的构造及初始化
5.1 如何初始化对象
在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败。
//编译成功public static void main ( String [] args ) {Date d = new Date ();d . setDate ( 2021 , 6 , 9 );d . printDate ();}
//编译失败public static void main ( String [] args ) {int a ;System . out . println ( a );}
5.2 构造方法
构造方法 ( 也称为构造器 ) 是一个特殊的成员方法, 名字必须与类名相同,在创建对象时,由编译器自动调用,并且 在整个对象的生命周期内只调用一次 。
- 构造方法:
- 名字与类名相同,没有返回值类型,设置为void也不行
- 一般情况下使用public修饰
- 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
public class Date {
public int year;
public int month;
public int day;
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date(2024,7,27); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2024-7-27
}
}
在上述代码运行中,构造方法只调用一次,由println可以看出
构造方法也是可以重载的,如下代码就是
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法
public Date(){
this.year = 2024;
this.month = 7;
this.day = 27;
}
// 带有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
如果没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。
public class Date {
public int year;
public int month;
public int day;
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
Date d = new Date();
d.printDate();
}
}
// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
// 但是this(1900,1,1);必须是构造方法中第一条语句
public class Date {
public int year;
public int month;
public int day;
public Date(){
//System.out.println(year); 注释取消掉,编译会失败
this(1900, 1, 1);
//this.year = 1900;
//this.month = 1;
//this.day = 1;
}
// 带有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
public Date (){this ( 1900 , 1 , 1 );}public Date ( int year , int month , int day ) {this ();}
为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?
1. 检测对象对应的类是否加载了,如果没有加载则加载2. 为对象分配内存空间3. 处理并发安全问题 比如:多个线程同时申请对象, JVM 要保证给对象分配的空间不冲突4. 初始化所分配的空间5. 设置对象头信息 ( 关于对象内存模型后面会介绍 )6. 调用构造方法,给对象中各个成员赋值
6. 封装
6.1 封装的概念
面向对象程序三大特性:封装,继承,多态,类和对象阶段,主要研究封装特性封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
举个例子
对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的, CPU 内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳 子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可 。
6.2访问限定符
Java 中主要通过类和访问权限来实现封装: 类可以将数据以及封装数据的方法结合在一起 ,更符合人类对事物的认知,而 访问权限用来控制方法或者字段能否直接在类外使用
一般情况下成员变量设置为 private,意味着这个类里面私有的成员变量 ,成员方法设置为 public,
public class Computer {
private String cpu; // cpu
private String memory; // 内存
public String screen; // 屏幕
}
如下代码,private只能类内部使用,外界无法访问
public class Main {
public static void main(String[] args) {
Date d1=new Date();
// d1.setDay(2024,4,4,5,5);
d1.printDate(d1.day);
d1.id();
}
}
6.3 包
包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式
在同一个工程中允许存在相同名称的类,只要处在不同的包中即可
Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类.
6.3.1 导入包
import java.util.Date;
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
double x = 30;
double y = 40;
double result = sqrt(pow(x, 2) + pow(y, 2));
System.out.println(result);
}
}
不用这样写类,语言更简洁
double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
6.3.2 自定义包
1. 在 IDEA 中先新建一个包 : 右键 src -> 新建 -> 包2.在弹出的对话框中输入包名 ,3. 在包中创建类 , 右键包名 -> 新建 -> 类 , 然后输入类名即可 .
![](https://i-blog.csdnimg.cn/direct/7a66390a1da04ab49d72540e1fb87974.png)
在文件的最上方加上一个 package 语句指定该代码在哪个包中 .如果一个类没有 package 语句 , 则该类被放到一个默认包中
![](https://i-blog.csdnimg.cn/direct/81089bda9e864d3bacd4e10cd796bdf0.png)
7. static成员
static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有类中的对象所共有的特征。注意:public可修改;
7.1 成员访问
静态成员变量可以直接通过类名访问,也可以通过对象访问,一般通过类名直接访问
注意事项:
1.不可在静态方法中访问非静态变量,如下图:
2.static成员是类的属性。所有的类都可以对他进行修改,如下图:
3.如上图,不属于某个具体的对象,是类方法
7.2 static成员变量初始化
1.直接初始化:在定义时直接给出初始值
2.静态代码块:
8.代码块
8.1 代码块概念
使用 {} 定义的一段代码称为代码块
8.2 代码块的分类
由代码块定义的位置,分为四类:
- 普通代码块
- 构造块
- 静态块
- 同步代码块
8.3 普通代码块
在方法中定义的代码块,比较少见
8.4 构造代码块
定义在类中的代码块吗,构造代码块一般用于初始化实例成员变量。
8.5 静态代码块
注意:静态代码块只执行一次,实例代码块只有在创建对象时才会执行
9.内部类
在Java中,可以将一个类定义在另一个类里面,用来描述一部分结构,这一部分称为内部类,另一个类称为外部类
public class OutClass {
class InnerClass{
}
}
// OutClass是外部类
// InnerClass是内部类
9.1 内部类的分类
- 未被static修饰 --->实例内部类
- 被static修饰 ---> 静态内部类
- 方法中也可以定义内部类 ---> 局部内部类
1,2合称为成成员内部类
9.2 实例内部类
- 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类的
- 在实例内部类中可以直接访问外部类中的任意访问限定符修饰的成员,可以访问private
- 如果要访问外部类同名成员时候,必须:外部类名称.this.同名成员名字
- 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。也可以先将外部类对象先创建出来,然后再创建实例内部类对象
public class Main {
public static void main(String[] args) {
{
int a=1;
int b=2;
int c=3;
}
//直接创建内部类对象
Date.DDate outER = new Date().new DDate(1,2,3);
outER.DAS4();
}
}
public static void main(String[] args) {
{
int a=1;
int b=2;
int c=3;
}
//可以先将外部类对象先创建出来,然后再创建实例内部类对象
Date date=new Date();
Date.DDate date1= date.new DDate(1,2,3);
}
}
实例内部类对象必须在先有外部类对象前提下才能创建
9.3 静态内部类
在内部类中只能访问外部类的静态成员
创建静态内部类对象时,不需要先创建外部类对象
9.4 局部内部类
定义在外部类的方法体或者{}中,只能在其定义的位置使用
class Date { public int year; public int month; private int id(){ class idd{ public int cs; public int go; public idd(int cs, int go) { this.cs = cs; this.go = go; } } idd id1 = new idd(0, 0); return month; }
10. 对象的打印
要打印对象中的属性应该重写toString方法
class Date {
public int year;
public int month;
private int id(){
class idd{
public int cs;
public int go;
public idd(int cs, int go) {
this.cs = cs;
this.go = go;
}
}
idd id1 = new idd(0, 0);
return month;
}
@Override
public String toString() {
return "["+year+"/"+month+"/"+id()+"]";
}
}
重写之后,主函数中调用代码如下
输出结果:
内部类同理,只需在内部类中重写toString方法即可
文章有什么问题都可以评论,私聊我哦,欢迎欢迎