面向对象编程
(Object Oriented Programing)
神速熟悉面向对象
表格结构和类结构
在生活中我们经常用到表格 ,“表格思维”就是一种典型的面向对象思维。互联网上的很多数据实际上就是表格,这里我们用表格来引入对象和类,大家会神奇的发现“表格就是对象”
ID | 姓名 | 岗位 | 工资 | 绩效 | 入职日期 |
1001 | 小秃头 | 程序员 | 10000 | 1000 | 2023/1/1 |
1002 | 老秃头 | 架构师 | 20000 | 2000 | 2021/1/1 |
1003 | 踩坑神 | 实习生 | 1000 | 0 | 2024/1/1 |
ID | 姓名 | 岗位 | 工资 | 绩效 |
1001 | 小秃头 | 程序员 | 10000 | 1000 |
1002 | 老秃头 | 架构师 | 20000 | 2000 |
1003 | 踩坑神 | 实习生 | 1000 | 0 |
表格的动作和类的方法
每个员工都会有相关的动作,比如1,参加晨会总结昨天的内容。2,午休
我们把动作也加进去
ID | 姓名 | 岗位 | 工资 | 绩效 | 入职日期 | 动作 |
1001 | 小秃头 | 程序员 | 10000 | 1000 | 2023/1/1 | 1.参加晨会总结昨天的内容 2.午休 |
1002 | 老秃头 | 架构师 | 20000 | 2000 | 2021/1/1 | |
1003 | 踩坑神 | 实习生 | 1000 | 0 | 2024/1/1 |
对象对应“表中行的数据”
ID | 姓名 | 岗位 | 工资 | 绩效 | 入职日期 |
1001 | 小秃头 | 程序员 | 10000 | 1000 | 2023/1/1 |
1002 | 老秃头 | 架构师 | 20000 | 2000 | 2021/1/1 |
1003 | 踩坑神 | 实习生 | 1000 | 0 | 2024/1/1 |
- 表结构对应:类结构
- 一行数据对应:一个对象
- 表中所有数据对应:这个类的所有对象
面向过程和面向对象思想
面向过程和面向对象的区别
面向过程和面向对象都是对软件分析、设计和开发的一种思想,它指导着人们以不同的方式去分析、设计和开发软件。C 语言是一种典型的面向过程语言,Java 是一种典型的面向对象语言。 面向过程适合简单、不需要协作的事务,重点关注如何执行。 面向过程时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。 这个适合简单任务,不需要过多协作的情况下。比如,如何开车?我们很容易就列出实现步骤: 点火--->挂挡--->踩油门--->走你 但是当我们思考比较复杂的设计任务时,比如“如何造车?”,就会发现列出这样的步骤,是不可能的。那是因为,造车太复杂,需要很多协作才能完成。此时面向对象思想就应运而生了。 面向对象(Oriented-Object)思想更契合人的思维模式。我们首先思考的是“ 怎么设计 这个事物?” 比如思考造车,我们就会先思考“车怎么设计?”,而不是“怎么按步骤造车的问题”。这就是思维方式的转变。![](https://i-blog.csdnimg.cn/direct/2ceaf1cd8a654d71b956a9676bb52683.jpeg)
面向对象和面向过程思想的总结
- 都是解决问题的思维方式,都是代码组织的方式。
- 面向过程是一种“执行者思维”,解决简单问题可以使用面向过程。
- 面向对象是一种“设计者思维”,解决复杂、需要协作的问题可以使用面向对象。
- 面向对象离不开面向过程:
- 宏观上:通过面向对象进行整体设计
- 微观上:执行和处理数据,仍然是面向过程。
对象和类详解
类可以看做是一个模版,或者图纸,系统根据类的定义来造出对象。我们要造一个汽车,怎么样造?类就是这个图纸,规定了汽车的详细信息,然后根据图纸将汽车造出来 类:我们叫做 class。 对象:我们叫做 Object,instance(实例)。以后我们说某个类的对象,某个类的实例。是一样的意思。总结
- 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
- 类是用于描述同一类型的对象的一个抽象概念,类中定义了这一类对象所应具有的共同的属性、方法
类的定义
类的定义方式:对于一个类来说,有三种成员:属性 field、方法 method、构造器 constructor 。
- // 每一个源文件必须有且只有一个public class,并且类名和文件名保持一致!
- public class Car {
- }
- class Tyre { // 一个Java文件可以同时定义多个class
- }
- class Engine {
- }
- class Seat {
- }
属性
属性定义格式: [修饰符] 属性类型 属性名 = [默认值] ; 例:int age = 18; 修饰符值确定该属性是开放的还是静态的不写默认public
方法
方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。[修饰符] 方法返回值类型 方法名(形参列表) { // n 条语句 } 例:public void Student(int age){ System.out.println(age); }编写简单的学生类
- public class SxtStu {
- //属性(成员变量)
- int id;
- String sname;
- int age;
- //方法
- void study(){
- System.out.println("我正在学习!");
- }
- //构造方法
- SxtStu(){
- }
- }
简单内存分析(方便理解面向对象)
- public class SxtStu {
- int id;
- int age;
- String sname;
- public void study(){
- System.out.println("学习");
- }
- public void kickball(){
- System.out.println("踢球");
- }
- public static void main(String[] args) {
- SxtStu s1=new SxtStu();
- System.out.println(s1.id);
- System.out.println(s1.sname);
- s1.id = 1001;
- s1.sname = "秃头";
- System.out.println(s1.id);
- System.out.println(s1.sname);
- }
- }
构造方法(构造器constructor)
构造方法是负责初始化(装修),不是建房子[修饰符] 类名(形参列表){ //n 条语句 } 例:public Student(int age){ System.out.println(age); } 少了返回类型相比于方法
构造器 4 个要点:
- 构造器通过 new 关键字调用!!
- 构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用 return 返回某个值。
- 如果我们没有定义构造器,则编译器会自动定义一个无参的构造方法。如果已定义则编译器不会自动添加!
- 构造器的方法名必须和类名一致!
构造方法的重载
构造方法重载(创建不同用户对象)public class User { int id ; // id String name ; // 账户名 String pwd ; // 密码 public User() { } public User( int id , String name ) { this . id = id ; this . name = name ; } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public static void main(String[ ] args ) { User u1 = new User(); User u2 = new User(101, "老秃头" ); User u3 = new User(100, "小秃头" , "123456" ); } }
雷区: 如果方法构造中形参名与属性名相同时,需要使用 this 关键字区分属性与形参。this.id 表示属性 id;id 表示形参 id
面向对象内存分析
秃头建议: 为了完整的体现内存分析流程,会有些新的名词,比如:线程、Class 对象。大家暂时可以不求甚解的了解
java虚拟机内存模型概念
- 虚拟机栈(简称:栈)的特点如下:
- 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
- JVM 为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
- 栈属于线程私有,不能实现线程间的共享!
- 栈的存储特性是“先进后出,后进先出”
- 栈是由系统自动分配,速度快!栈是一个连续的内存空间!
- 堆的特点如下:
- 堆用于存储创建好的对象和数组(数组也是对象)
- JVM 只有一个堆,被所有线程共享
- 堆是一个不连续的内存空间,分配灵活,速度慢!
- 堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分
- 方法区(也是堆)特点如下:
- 方法区是 JAVA 虚拟机规范,可以有不同的实现。
- JDK7 以前是“永久代”
- JDK7 部分去除“永久代”,静态变量、字符串常量池都挪到了堆内存中
- JDK8 是“元数据空间”和堆结合起来。
- JVM 只有一个方法区,被所有线程共享!
- 方法区实际也是堆,只是用于存储类、常量相关的信息!
- 用来存放程序中永远是不变或唯一的内容。(类信息【Class 对象,反射机制中会重点讲授】、静态变量、字符串常量等)
- 常量池主要存放常量:如文本字符串、final 常量值。
参数传递机制
Java 中,方法中所有参数都是“值传递”,也就是“传递的是值的副本”。 也就是说,我们得到的是“原参数的复印件,而不是原件”。 基本数据类型参数的传值: 传递的是值的副本。 副本改变不会影响原件。 引用类型参数的传值: 传递的是值的副本。但是引用类型指的是“对象的地址”。因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值,也意味着原参数指向对象的值也发生了改变”。多个变量指向同一个对象:垃圾回收机制请见其他文章public class User {
int id;
//id
String name; //账户名
String pwd; //密码
public User( int id, String name) { this . id = id; this . name = name; } public static void main(String[ ] args) { User u1 = new User(100, "秃头" ); User u3 = u1; System. out .println(u1. name ); u3. name = "张三" ; System. out .println(u1. name ); } } 结果: 秃头 张三
关键字
this关键字
this的用法
- 普通方法中,this 总是指向调用该方法的对象。
- 构造方法中,this 总是指向正要初始化的对象。
- this()调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句。
- this 不能用于 static 方法中。
- this 是作为普通方法的“隐式参数”,由系统传入到方法中。
this用法详讲
public class TestThis {
int a, b, c;
TestThis() {
System.out.println("正要初始化一个Hello对象");
}
TestThis(int a, int b) {
// TestThis(); //这样是无法调用构造方法的!
this(); // 调用无参的构造方法,并且必须位于第一行!
a = a;// 这里都是指的局部变量而不是成员变量
// 这样就区分了成员变量和局部变量. 这种情况占了this使用情况大多数!
this.a = a;
this.b = b;
}
TestThis(int a, int b, int c) {
this(a, b); // 调用带参的构造方法,并且必须位于第一行!
this.c = c;
}
void sing() {
}
void eat() {
this.sing(); // 调用本类中的sing();
System.out.println("你妈妈喊你回家吃饭!");
}
public static void main(String[ ] args) {
TestThis hi = new TestThis(2, 3);
hi.eat();
}
}
static关键字
- 为该类的公用变量,属于类,被该类的所有实例共享,在类载入时被初始化。
- static 变量只有一份。
- 一般用“类名.类变量/方法”来调用。
- 在 static 方法中不可直接访问非 static 的成员。
static关键字的使用
public class TestStatic {
int id; // id
String name; // 账户名
String pwd; // 密码
static String Bo= "CSDN";
public TestStatic (int id, String name) {
this.id = id;
this.name = name;
}
public void login() {
System.out.println(name);
}
public static void printCompany() {
// login();//调用非静态成员,编译就会报错
System.out.println(company);
}
public static void main(String[ ] args) {
TestStatic u = new TestStatic (101, "秃头");
TestStatic .printCompany();
TestStatic .Bo= "CSDN秃头";
TestStatic .printCompany();
}
}
/**
*结果是
*CSDN
*CSDN秃头
*/
静态初始化块
构造方法用于对象的普通属性初始化。 静态初始化块,用于类的初始化操作,初始化静态属性。 在静态初始化块中不能直接访问非 static 成员
注意事项 静态初始化块执行顺序(会继承再看这里):
- 上溯到 Object 类,先执行 Object 的静态初始化块,再向下执行子类的静态初始化块,
- 直到类的静态初始化块为止。
- 构造方法执行顺序和上面顺序一样!!
static 静态初始化块
public class TestStatic2 {
static String company; //名称
static {
System.out.println("执行类的初始化工作");
company = "CSDN";
printCompany();
}
public static void printCompany(){
System.out.println(company);
}
public static void main(String[ ] args) {
}
}
/**
*结果是
*执行类的初始化工作
*CSDN
*/
包机制
相当于文件夹
package 的使用有两个要点:
- 通常是类的第一句非注释性语句。
- 包名:域名倒着写即可,便于内部管理类。
package 的命名演示 com.oracle.test; com.itbaizhan.gao.test; com.itbaizhan.gao.view; com.itbaizhan.view.model;
注意事项 写项目时都要加包,不要使用默认包。 com.gao 和 com.gao.car,这是两个完全独立的包。只是逻辑上看,后者是前者的一部分
在IDEA中新建项目包路径
点击 OK,即可在 src 下面看到包
JDK中的主要包
注意要点静态导入(static import): 其作用是用于导入指定类的静态属性和静态方法,这样我们可以直接使用静态属性和静态方法 静态导入的使用:
- Java 会默认导入 java.lang 包下所有的类,因此这些类我们可以直接使用。
- 如果导入两个同名的类,只能用包名+类名来显示调用相关类:java.util.Date date = new java.util.Date();
package com.itbaizhan;
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
public class Test2{
public static void main(String [ ] args){
System.out.println(PI);
System.out.println(random());
}
}
面向对象三大特征 重点针对面向对象编程的三大特征:继承、封装、多态进行详细的讲解。 不要期望,通过学习就“搞透面向对象编程”。本章只是面向对象编程的起点,后面所有的章节说白了都是对面向对象这一章的应用。
秃头建议: 建议大家,学习本章,莫停留!学完以后,迅速开展后面的章节。可以这么说, 后续章 节 所有的编程都是“面向对象 思想 ”的应用而已!标签:java,String,int,不行,id,面向对象,static,勇闯,public From: https://blog.csdn.net/2201_75777992/article/details/140227944