Java基础部分详解(二)--->面向对象

简介: 1. 此篇接Java基础部分详解(一)2. 该篇主要阐述了Java中最重要的概念面向对象!!3. 要学会画内存图,分析出代码的执行流程

面向对象

😀day13

8.1.  认识面向过程


c语言 面向过程


c++  一半面向对象 一半面向过程


java 完全面向对象


面向过程(耦合度高,可扩展性差):注重功能的步骤以及整个过程一体机,某个零部件坏了,所有的都坏了。


缺点:面向过程最主要是每一步与每一步的因果关系,假设其中任何一个因果关系出现问题(错 误),此时


整个系统的运转都会出现问题。(代码和代码之间的耦合度太高,扩展力太差。


优点:对于小型项目(功能),采用面向过程的方式进行开发,效率较高耦合度:就是粘连程度。


8.2.  认识面向对象


面向对象(耦合度底,可扩展性高):关注度在对象,更符合人类的组装电脑,某个零件坏了,只需要更换那某个零件。采用面向对象开发,更符合人类的思维方式


  • 采用面向对象的方式贯穿整个系统的话,涉及到三个术语:
    OOA面向对象分析
    OOD面向对象设计
    OOP面向对象编程


整个软件开发的过程,都是采用OO进行贯穿的。


实现一个软件的过程:分析(A) --> 设计(D) --> 编程(P)


8.3.  面向对象三大特征


封装 继承 多态


任何一个面向对象的编程语言都包括这三个特征


8.4.  类和对象


8.4.1. 类


  • 什么是类:类实际上在现实世界当中是不存在的,是一个抽象的概念。类就是是一个模板,通过一个 类,是可以创建N多个对象的。
  • java中所有的“类”都属于引用数据类型。


8.4.2. 对象


  • 什么是对象:对象是实际存在的个体。(真实存在的个体)
  • 在java语言中,要想得到“对象”,必须先定义“类”,“对象”是通过“类”这个模板创造出来的。
  • 这几个术语你需要自己能够阐述出来:
  • 类:不存在的,人类大脑思考总结一个模板(这个模板当中描述了共同特征。)
  • 对象:实际存在的个体。
  • 实例:对象还有另一个名字叫做实例。
  • 实例化:通过类这个模板创建对象的过程,叫做:实例化。
  • 抽象:多个对象具有共同特征,进行思考总结抽取共同特征的过程。
    类 --【实例化】--> 对象(实例)
    对象 --【抽象】--> 类
  • 类 = 属性 + 方法
    属性来源于:状态         n   属性其实就是成员变量 方法来源于:动作v


😸思考:“java软件工程师”在开发中起到的一个作用是什么?


  • 软件开发既然是为了解决现实世界当中的问题,那么首先java软件必须能够模拟现实世界。
  • 其实软件是一个虚拟的世界。这个虚拟的世界需要和现实世界一一对应,这才叫模拟。


8.4.3. 类的定义


  1. 语法格式:
    [修饰符列表]  class 类名 {
    //类体 = 属性 + 方法
    // 属性在代码上以变量的形式存在(描述状态),属性其实就是变量。
    // 方法描述动作/行为
    }


  • 属性对应的是“数据”,数据在程序中只能放到变量中。属性其实就是对象级别的变量。
  • 变量根据出现位置进行划分:
    方法体当中声明的变量:局部变量。
    方法体外声明的变量:成员变量。(这里的成员变量就是属性)


8.5.  编译的过程


第一种方式:


javac XueSheng.java javac XueShengTest.java


第二种方式:


java XueShengTest.java   jdk14的新特性


第三种方式:


javac *.java


8.6.  对象的创建


语法级别上是怎么完成对象创建: 类名 变量名 = new 类名();这样就完成了对象的创建。


new是一个运算符。专门负责对象的创建。


public class XueSheng{ // 这个程序编译之后,会生成XueSheng.class字节码文件。

// 属性

// 学号(成员变量)

int xueHao;

// 姓名

String xingMing;

// 年龄

int nianLing;

// 性别

boolean xingBie;

// 住址

String zhuZhi;

}


public class XueShengTest{

public static void main(String[] args){

int i = 100;

System.out.println("i =" + i);

// 在这里可以访问XueSheng类吗?

// 当然可以。

/*

创建对象的语法是什么? new 类名();

目前死记硬背,先记住。后面你就理解了。

XueSheng s1 = new XueSheng();

int i = 100;

解释一下:i是变量名

int是变量的数据类型

100是具体的数据。

s1是变量名(s1不能叫做对象。s1只是一个变量名字。)

XueSheng是变量s1的数据类型(引用数据类型)

new XueSheng() 这是一个对象。(学生类创建出来的学生对象。)

数据类型包括两种:

基本数据类型:byte short int long float double boolean    char

引用数据类型:String、XueSheng.....

java中所有的“类”都属于引用数据类型。

*/

XueSheng s1 = new XueSheng(); // 和 int i = 10;一个道理。

// 再通过该类创建一个全新的对象

XueSheng s2 = new XueSheng();

// 再创建一个呢?

XueSheng xsh = new XueSheng();

// 以上的这个程序就相当于通过XueSheng类实例化了3个XueSheng对象。

// 创建对象的个数没有限制,可以随意。只要有模板类就行。

// 3个对象都属于学生类型。

}

}


  • 什么是实例变量?
    对象又被称为实例。
    实例变量实际上就是:对象级别的变量。
    成员变量也叫实例变量。


  • 对象和引用的区别
    对象是通过new出来的,在堆内存中存储。
    引用是:但凡是变量,并且该变量中保存了内存地址指向了堆内存当中的对象的。


  • 对象级的变量(实例变量)的调用 引用.实例变量


  • 实例变量的赋值
    引用.实例变量 =
    通过“=”赋值的方式将内存中实例变量的值修改一下。
  • 实例变量的访问
    先创建对象,然后""引用."的方式访问。


8.7.  对象的使用


public class StudentTest{

public static void main(String[] args){

       //局部变量,错误: 可能尚未初始化变量k

       /*

       int k;

       System.out.println(k);

       */

       / 创建学生对象1

       // s1属于局部变量吗?当然是。

       // s1这个局部变量叫做引用

       Student s1 = new Student();

       // 怎么访问实例变量?

       // 语法:引用.实例变量名

       System.out.println(s1.no);

       System.out.println(s1.name);

       System.out.println(s1.age);

       System.out.println(s1.sex);

       System.out.println(s1.addr);

       // 程序执行到此处我可以修改s1这个学生的学号吗?

       // 通过“

       =

       ”赋值的方式将内存中实例变量的值修改一下。

       s1.no = 110;

       s1.name =

       "张三";

       s1.age = 20;

       s1.sex = true;

       s1.addr =

       "深圳宝安区";

       System.out.println("学号=

       " + s1.no);

       System.out.println("姓名=

       " + s1.name);

       System.out.println("年龄=

       " + s1.age);

       System.out.println("性别=

       " + s1.sex);

       System.out.println("住址=

       " + s1.addr);

}

public static void method(){

   // i s1 s2都是main方法中的局部变量,在这里是无法访问的。

   /*

   System.out.println(i);

   System.out.println(s1);

   */

}

}


  • Student s1 = new Student();
  • s1属于局部变量 ,叫做引用。
  • s1是变量名
  • Student是数据类型(引用数据类型)
  • new Student() 这是一个对象(学生类创建出来的学生对象。)


8.8 对象和引用


  • jvm内存执行图

  • java中没有指针概念,没法直接使用堆内存
  • 将堆内存中对应的对象地址复制一份,赋值给s1变量,实现间接调用
  • 引用和对象的区分:

引用是存储对象地址的一个变量,引用不一定是局部变量

对象是堆里new出来的。成员变量里面包含实例变量

  • 此图中的代码只是为了方便理解,画内存图是应没有代码,只有数据。
  • 引用 指向对象的过程 在c语言里面叫指针


8.9.  成员变量的默认值


注意:对于成员变量来说,没有手动赋值时,系统默认赋值


  • 引用数据类型是null。
  • null是一个java关键字,全部小写,表示空。是引用类型的默认值。byte、short、int是0。
  • long 是 0L
  • float 是 0f double是0.0
  • Boolean 是 false
  • char是     \u0000

系统赋的默认值会接近与0

8.10.  JVM内存图复习


网络异常,图片无法展示
|


  • 注意:只要是方法,不管静态方法、实例方法、构造方法,它们在运行的时候都会在栈内存压栈。


8.11.  Homework


题目1:根据程序画执行内存图



答案:


只有地址指向对象,没有对象指向地址。



题目二:难度较大 画程序执行内存图 并完成思考题




思考题:


答案:Address.u.city;

  正确答案:u.addr.city

  拆分代码:


内存图:




9.  面向对象 (二)


💡day 14


9.1.  内存图 (重要)


9.1.1. 画内存图注意事项


  • 不要在内存图体现代码,应该体现数据
  • 画图时,应分析代码。根据代码一行一行的去画。
  • 引用的箭头永远指向对象。


9.1.2. HomeWork1


画内存图


// 把这个内存图画出来。

一定要按照程序的执行顺序一步一步画。

public class T{

  A o1; // 成员变量中的实例变量。必须先创建对象,通过“引用”来访问。

  public static void main(String[] args){

      D d = new D();

      C c = new C();

      B b = new B();

      A a = new A();

      T t = new T();

      //这里不写代码会出现 NullPointerException 异常。(空指针异常。)

      c.o4 = d;

      b.o3 = c;

      a.o2 = b;

      t.o1 = a;

      // 编写代码通过 t 来访问 d 中的 i

      //System.out.println(T.a); //错误的。

      System.out.println(t.o1.o2.o3.o4.i);

  }

}

class A{

B o2;

}

class B{

C o3;

}

class C{

D o4;

}

class D{

int i;

}


  • 为什么要画内存图(非常重要)?
    第一:有了内存图,程序不运行,我也知道结果。(可以推算出结果)
    第二:有了内存图,有助于你调试程序。


9.2.  空指针异常( NullPointerException )


  • 关于垃圾回收器:GC机制

在java语言中,垃圾回收器主要针对的是堆内存。当一个java对象没有任何引用指向该对象 的时候,GC会考虑将该垃圾数据释放回收掉。

  • 出现空指针异常的前提条件是?
    "空引用"访问实例【对象相关】相关的数据时,都会出现空指针异常。
    空引用: 引用 = null ,没有指向对象,即为空引用。
    语法上是可以通过空指针异常。


public class NullPointerTest{

  public static void main(String[] args){

// 创建客户对象

      Customer c = new Customer();

// 访问这个客户的id

      System.out.println(c.id); // 0

      // 重新给id赋值

      c.id = 9521; // 终身代号

      System.out.println("客户的id是= " + c.id);

      c = null; // 没用引用指向对象 Gc机制清理堆内存的对象

      // NullPointerException 空指针异常

      // 编译器没问题,因为编译器只检查语法,编译器发现c是Customer类型,

      // Customer类型中有id属性,所以可以:c.id。语法过了。

      // 但是运行的时候需要对象的存在,但是对象没了,尴尬了,就只能出现一个异常。

      System.out.println(c.id);

    }

}

class Customer{

// 客户id

int id; // 成员变量中的实例变量,应该先创建对象,然后通过“引用.

”的方式访问。

}


内存图:



9.3.  方法调用时参数传递的问题


  • java中规定:参数传递的时候,和类型无关,不管是基本数据类型还是引用数据类型,统一都是将 盒子中保存的那个“值”复制一份,传递下去。
  • java中只有一个规定:参数传递的时候,一定是将”盒子”中的东西复制一份传递过去。 内存地址也是值,也是盒子中保存的一个东西。


  • 方法的参数可以是引用数据类型也可以是基本数据类型
  • 分析以下代码
  • int x = 1; int y = x;
    分析:把x中保存1复制一份传给y,x和y都是两个局部变量。
  • Person p1 = 0x1234; Person p2 = p1;
    分析:把p1中保存的0x1234复制一份传给p2,p1和p2都是两个局部变量。


public class Test1{

   public static void main(String[] args){

       int x = 100;

       int y = x; // x赋值给y,是怎么传递的?将x变量中保存的100这个值复制一份传给y

       // 局部变量,域是main

       int i = 10;

       // 将i变量中保存的10复制一份,传给add方法。

       add(i);

       System.out.println("main ---> " + i); //10

   }

   /*

   public static void add(int i){ // i是局部变量,域是add

       i++;

       System.out.println("add ----> " + i); //11

   }

   */

public static void add(int k){

       k++;

       System.out.println("add ----> " + k);

   }

}


public class Test2{

public static void main(String[] args){

Person p = new Person();

p.age = 10;

add(p);

System.out.println("main--->" + p.age); //11

}

// 方法的参数可以是基本数据类型,也可以是引用数据类型,只要是合法的数据类型就行。

public static void add(Person p){ // p是add方法的局部变量。

p.age++;

System.out.println("add--->" + p.age); //11

}

}

class Person{

// 年龄属性,成员变量中的实例变量。

int age;

}


内存图Test1:


内存图Test2



9.4.  构造方法(重点)


9.4.1. 构造方法特点( Constructor )


  1. 什么是构造方法?


  • 构造方法是用来创建对象,并同时给对象的属性赋值。(注意:实例变量没有手动赋值的时候,系统会赋默认值。)


  1. 构造方法语法:
    [修饰符列表]   构造方法名(形式参数列表){  

构造方法体;
通常在构造方法体当中给属性赋值,完成属性的初始化。

}

  • 修饰符列表目前统一写:public,千万不要写public static,
  • 构造方法名和类名必须一致。
  • 构造方法不需要指定返回值类型,也不能写void,写上void表示普通方法,就不是构造方法了。


  1. 当一个类中没有提供任何构造方法,系统默认提供一个无参数的构造方法。这个无参数的构造方法叫做缺省构造器。


  1. 调用构造方法:使用new运算符来调用构造方法。语法格式:new  构造方法名(实际参数列表);


  • 当一个类中手动的提供了构造方法那么系统将不再默认提供无参数构造方法。建议将无参数构造 方法手动的写出来,这样一定不会出问题。


  • 无参数构造方法和有参数的构造方法都可以调用。
    Student x = new Student();
    Student y = new Student(123);


  • 构造方法支持方法重载吗?
  • 构造方法是支持方法重载的。在一个类当中构造方法可以有多个。并且所有的构造方法名字 都是一样的。
  • 方法重载特点:在同一个类中,方法名相同,参数列表不同。


  • 对于实例变量来说,只要你在构造方法中没有手动给它赋值,统一都会默认赋值。默认赋系统值。 并且在构造方法中不显示,但存在。


public class ConstructorTest01{

  public static void main(String[] args){

  // 调用Student类的无参数构造方法

  new Student(); // 没用引用指向 会被自动清理

  // 调用普通方法

  ConstructorTest01.doSome();

  doSome();

  // 创建Student类型的对象

  Student s1 = new Student();

  // 输出“引用”

  //只要输出结果不是null,说明这个对象一定是创建完成了。

  // 此处的输出结果大家目前是看不懂的,后期再说。

  System.out.println(s1); //Student@54bedef2

  // 这是调用另一个有参数的构造方法。

  Student s3 = new Student(100);

  System.out.println(s3); //Student@5caf905d

  }

  public static void doSome(){

      System.out.println("do some!!!!");

  }

}


  • 思考:实例变量没有手动赋值的时候,系统会默认赋值,那么这个默认赋值操作是在什么时间进行的?
    实例变量是在构造方法执行的过程中完成初始化的,完成赋值的。


public class User{

// 3个属性,3个实例变量【对象变量】

// 用户id

  int id; //System.out.println(User.id);错误的。需要先new对象,只有对象有

  了才能谈id

  // 用户名

  String name;

  // 年龄

  int age;

// 手动定义有参数的构造方法,无参数构造方法将消失。

  public User(int a){

  }

  public User(){

      //这里实际上有三行代码你看不见。

      // 无参数构造方法体当中虽然什么代码都没写,

      // 但是实际上是在这个方法体里面进行的实例变量默认值初始化

      /*

      id = 0;

      name = null;

      age = 0;

      */

      // 这就表示不再采用系统默认值,手动赋值了。

      id = 111;

      name =

      "lisi";

      age = 30;

   }

}


  • 构造方法需要掌握的知识点:
  • 构造方法有什么作用?
  • 构造方法怎么定义,语法是什么?
  • 构造方法怎么调用,使用哪个运算符? 什么是缺省构造器?
  • 怎么防止缺省构造器丢失?
  • 实例变量在类加载是初始化吗?实例变量在什么时候初始化?
相关文章
|
1月前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
26 2
|
3月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
3月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
35 4
|
3月前
|
Java
接口和抽象类【Java面向对象知识回顾②】
本文讨论了Java中抽象类和接口的概念与区别。抽象类是不能被实例化的类,可以包含抽象和非抽象方法,常用作其他类的基类。接口是一种纯抽象类型,只包含抽象方法和常量,不能被实例化,且实现接口的类必须实现接口中定义的所有方法。文章还比较了抽象类和接口在实现方式、方法类型、成员变量、构造方法和访问修饰符等方面的不同,并探讨了它们的使用场景。
接口和抽象类【Java面向对象知识回顾②】
|
2月前
|
存储 Java 程序员
Java基础-面向对象
Java基础-面向对象
18 0
|
4月前
|
Java 数据处理 开发者
【Java基础面试十二】、说一说你对面向对象的理解
这篇文章阐述了面向对象是一种以类和对象为基础,通过封装、继承和多态等概念来模拟现实世界中的事物及其相互关系的程序设计方法,它强调以事物为中心进行思考和系统构造,与结构化程序设计相比,更符合人类的自然思维方式。
【Java基础面试十二】、说一说你对面向对象的理解
|
3月前
|
安全 Java Go
面向对象程序设计语言:Java
Java语言语法和C语言和C++语言很接近,很容易学习和使用,Java丢弃了C++中很少使用的、很难理解的、令人迷惑的特性,Java语言不使用指针,而是引用,并提供了自动分配和回收内存空间,使得程序员不必为内存管理而担忧
65 2
|
4月前
|
Java
【Java基础面试十三】、面向对象的三大特征是什么?
这篇文章介绍了面向对象程序设计的三大基本特征:封装、继承和多态,其中封装隐藏对象实现细节,继承实现软件复用,多态允许子类对象表现出不同的行为特征。
【Java基础面试十三】、面向对象的三大特征是什么?
|
3月前
|
Java 开发者
Java 面向对象
Java 是一种面向对象的编程语言,通过对象与类的概念组织代码和数据。面向对象编程的核心包括类、对象、继承、多态、封装和抽象。类是对象的蓝图,定义了属性和行为;对象则是类的实例。继承允许子类继承父类的属性和方法,增强代码复用性;多态则支持通过相同接口调用不同类型对象的行为,包括方法重载和重写。封装通过公共方法隐藏对象细节,提高安全性;抽象则对对象特征进行提炼,通过抽象类和接口实现。理解这些概念有助于设计高效、可维护的 Java 应用程序。
23 0
|
4月前
|
Java 开发者 C++