面向对象下知识点java_跟着刚哥梳理java知识点——面向对象(八)

2023-11-09 18:20

本文主要是介绍面向对象下知识点java_跟着刚哥梳理java知识点——面向对象(八),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

面向对象的核心概念:类和对象。

类:对一类事物描述,是抽象的、概念上的定义。

对象:实际存在的该类事物的每个个体,因而也成为实例(Instance)。

Java类及类的成员:属性(成员变量Field)和方法(method)。

类对象的内存结构:

8e8c9e59075c311b68f07e8d3f6511ae.png

Animal a1 = newAnimal();

a1.name= "花花";

a1.age= 3;

之前梳理数组的时候说过,栈中的对象存放对象的引用及Animal a1的a1这个引用。堆空间都是new出的东西包括成员变量。

① 在栈中声明一个a1的引用变量

② 在堆中申请一块区域存储new Animal并为成员变量赋默认值(name=null,age=0)。

③ a1的引用变量指向堆的new Animal的首地址(16进制数字)。

④ a1.name="花花":修改成员变量name值为花花。

⑤ a1.age = 3:修改成员变量age值为3。

Animal a2 = new Animal();

每次new出来的对象都是在堆中重新申请的一个新空间

Animal a3 = a1;

a3.name = "草草"

① 在栈中声明一个a3的引用变量

② a3的引用变量指向a1的指向的堆空间的首地址

③ a3.name = "草草":修改成员变量name值为"草草"。

最终,a1和a3的成员变量name都修改成了草草。

类的== 和equals

== 表示对象引用的地址是否相等,即16位的首地址码是否一致。

类没有重写equals,所以用的是Object的equals的方法,看源码就能看出来,和==一样。

想让比较的两个类所有属性值都一样的情况下就相等的话,需要自己重写equals方法。

类的成员之一:属性

成员变量(属性)和局部变量

7057930b31bbcf9c186ed0d6448b69c7.png

1、修饰符

① 成员变量:public、private、protected、default、final、static

② 局部变量:final

笔试题:

public classaClass {voidrun() {static int i = 0;

i++;

System.out.println(i);

}public static voidmain(String args[]) {

aClass obj= newaClass();

obj.run();

obj.run();

}

}

结果为:A:0    B:1    C:2    D:编译错误

很明显是选D,因为局部变量只能用修饰符final修饰。

2、默认初始化值:

① 局部变量:类的局部变量和数组元素的默认初始化值一致的。

② 成员变量:没有默认值。

3、内存中存放的位置:

① 局部变量:堆

② 成员变量:栈

51120ba693a12a8559ec67b136b1c1e3.png

① 在栈中声明一个p1的引用变量

② 在堆中申请一块区域存储new Person并为成员变量赋默认值(name=null,age=0,sex=false)。

③ p1的引用变量指向堆的new Person的首地址(16进制数字)。

④ 在栈中申请n的变量并赋值为付昊(n为形参的参数名字)

⑤ 将n这个局部变量的值赋值给刚才new Person的成员变量name

⑥ setName执行完毕后,n这个局部变量销毁。

4、类对象的属性赋值顺序:

① 属性的默认值:private int age;

② 属性的显式赋值:private int age = 1;

③ 构造器给属性赋值:public Person(int a){age = a;}

④ 通过setter方法赋值:public void setAge(int n){age = n;}

类的成员之二:方法

1、修饰符:private、protect、public、static、final、synchronize。

2、重载:方法名字相同,参数列表不同(参数个数不同和类型不同)。

3、重写:继承中子类重新实现了父类的方法。

① 要求子类方法名字和参数列表完全和父类一样。

② 子类方法的修饰符不能小于父类方法的修饰符。

4、形参:

java中的参数传递机制:值传递

① 基本数据类型传递(传递的值是具体的实参的基本数据类型的值)

public classTestArgsTransfer {public void swap(int i,intj){int temp =i;

i=j;

j=temp;

}public static voidmain(String[] args){

TestArgsTransfer tt= newTestArgsTransfer();int i = 10;int j = 5;

tt.swap(i,j);

}

}

内存结构

9d6369af323940517dc99c2d69d0960e.png

② 引用数据类型传递(传递的值是引用对象的16位的首地址值)

public classTestArgsTransfer {public voidswap(DataSwap d){int temp =d.i;

d.i=d.j;

d.j=temp;

}public static voidmain(String[] args){

TestArgsTransfer tt= newTestArgsTransfer();

DataSwap ds= newDataSwap();

tt.swap(ds);

}

}classDataSwap{int i = 10;int j = 5;

}

82054e623b01b38d7f0b448491796102.png

类的成员之三:构造器:

特点:

① 和类名字一致

② 没有返回值

③ 只能被4个访问权限修饰符修饰

作用:

① 创建对象

② 给创建的对象的属性赋值,通过构造器的形参实现。

【知识点】:

① 若不显式的声明类的构造器的话,程序会默认的提供一个空参的构造器。

② 若显式的声明的类的构造器的话,那么默认的构造器就不再提供。

③ 类的多个构造器之间形成重载。

java封装性:

1、将属性私有化,然后通过调用getter和setter方法来获取或者设置属性。

为什么不直接使用对象.属性直接使用属性呢?

设想,你有一个Person类代表一个人,Person有一个char类型的sex字段表示性别,理论上,sex只接受两个值, 'M '和 'F ',但如果你把sex字段设为public,

你很难限制你的用户只给它赋 'M '或 'F '值。将sex设为private,再用setSex()来设置性别,你就完全可以控制这种行为了。而且你还可以控制只能get不能set,

或相反,但如果是public就不行了。另外我们可能并不想对属性进行写操作,这个时候,可以直接不写set方法。这就是只读属性了。

2、通过4种访问权限修饰符隐藏了类或者方法

238663c6c23c5ac72bea0ae450819cd2.png

java继承性:extends

1、子类继承父类后,父类中声明的属性、方法,子类就可以获取到。

2、子类除了通过继承,获取父类的结构之外,还可以定义自己特有的成分。

3、java中的类只支持单继承,不支持多继承。

4、由于Object是所有类的超类,那么你在最顶层的父类其实还会调用Object的无参构造函数。

子类对象实例化的全过程

1 public classMain {2 public static voidmain(String[] args) {3 Dog dog = newDog();4 dog.setAge(10);5 dog.setName("花花");6 dog.setHostName("小明");7 System.out.println("age:" + dog.getAge() + "\nname:" + dog.getName() + "\nhostname:" +dog.getHostName());8 }9 }10 //生物

11 classCreator{12 private intage;13 public intgetAge() {14 returnage;15 }16 public void setAge(intage) {17 this.age =age;18 }19 }20 //动物

21 class Animal extendsCreator{22 privateString name;23 publicString getName() {24 returnname;25 }26 public voidsetName(String name) {27 this.name =name;28 }29 }30 //狗

31 class Dog extendsAnimal{32 privateString hostName;33 publicString getHostName() {34 returnhostName;35 }36 public voidsetHostName(String hostName) {37 this.hostName =hostName;38 }39 }

d64f61711c4cc793184ff980c4bcd097.png

子类对象的实例化并没有在堆中创建了任何它的父类对象,只是把父类对象的属性带了过来。

java多态性

多态性:可以理解为一个事物的多种表现形态。

1、方法的重载与重写

同一类中方法名相同,但是调用子类和父类的表现却是不同的。

2、子类对象的多态性

Person p = new Student(); //子类对象的多态性,父类的引用指向子类对象//虚拟方法调用:实际调用子类重写父类的方法,但是父类必须有此方法声明

p.eat();

p.walk();

3、向下转型和向上转型

Person p = new Student();//向上转型

Student s = (Student)p;//向下转型,强制类型转换

但是这种转型是有一些风险的,那么最好用instanceof来判断

4、子类对象的多态性,并不适用属性。加入父类和子类的属性值相同,左边是谁,就使用谁的属性。

匿名类对象:

1、创建类的对象是没有名字的。

2、使用场景:当我们只需要调用一次类的对象时。

3、特点:创建的对象调用完一次这个对象就销毁了。

new Person().getName;

关键字:

1、this

this表示当前对象,用来修饰属性、方法、构造器

在构造器内部,this必须声明在首行。

classCake{privateString name;publicCake(){

System.out.println("cake");

}publicCake(String name){this();//this调用无参的构造器

this.name = name;//this调用当前对象

}

}

2、super

this表示父类对象,用来修饰属性、方法、构造器

在构造器内部,supper必须声明在首行。

在构造器内部,子类构造器都默认第一步调用父类无参的构造器,除非你加了this,因为只要加了this的话super就不起作用了。

1 classPerson{2 publicPerson(){3 System.out.println("p1");4 }5 public Person(intid,String name){6 this();7 System.out.println("p2");8 }9 }10 class Student extendsPerson{11 publicStudent(){12 System.out.println("s1");13 }14 publicStudent(String n){15 System.out.println("s2");16 }17 public Student(intg){18 this("s");19 System.out.println("s3");20 }21 }22 public classMain {23 public static voidmain(String[] args){24 Student student = new Student(0);25 }26 }

输出结果:p1 s1 s2

总结:

① 在构造器内要么用this要么用super,用了this,super就会失效。

② 在构造器内如果子类不显式的调用父类的构造器,那么默认调用无参的super();

③ 设计父类的时候,如果不显式的声明一个无参的构造函数,那么有可能造成程序编译错误。

3、static

静态的,可以修饰属性、方法、代码块、内部类

1)属性(类变量):

classSportsMan {

String name;intage;staticString nation;public SportsMan(String name, intage) {super();this.name =name;this.age =age;

}

}

d0e53730d7d48be44e46e4d3c8c79aa6.png

总结:

① SportsMan类中的nation属性是static修饰的,由这个类创建的对象都共用这个属性。

② 类变量的加载早于对象,所以既可以用“sp1.nation”,也可以用“SportsMan.nation”调。

③ 当其中一个对象对此类变量进行修改,会影响其他对象的类变量的一个调用。

2)方法:

① 随着类的加载而加载,在内存中也是独一份。

② 可以直接通过“类.类方法”

③ 静态方法内部可以调用静态的属性或者方法,但是不能调用非静态的属性和方法,因为静态的生命周期要早于非静态对象。

④ 非静态的方法可以调用静态的属性和方法,因为非静态的方法晚于静态的方法和属性。

4、final

① 修饰类 :不能被继承

② 修饰方法:不能被重写

③ 修饰属性:此属性就是一个常量。此常量不能使用默认初始化(除非在构造器中或者非静态代码块初始化),可以显式的赋值。

1 final int I;//编译错误

2 final int I = 12;//正确

3 public voidm(){4 I = 15; //编译错误

5 }

但是如果放在构造器中,就没问题。

1 final int I;//正确

2 publicA(){3 I = 15;//正确

4 System.out.println("3");5 }

笔试题一:

1 public classSomething{2   public int addOne(final intx){3     return ++x;4   }5 }

肯定编译错误,final一旦修饰的时候赋了值,那么对不起,我的值就是最终的值,以后谁都不能改,谁改谁错。

笔试题二:

1 public classSomething{2   public static voidmain(String[] args){3     Other o = newOther();4     newSomething.addOne(o);5   }6   public void addOne(finalOhter o){7     o.i++

8   }9 }10 classOther{11   public inti;12 }

肯定不出错,final修饰的是o(即o的堆地址),o里的属性没关系,想怎么变就怎么变。

类的成员之四:初始化块

1)非静态块

1 classPerson{2 int id = 0;3 String name = "n";4 {5 id = 10;6 name = "ni";7 System.out.println("你好:你");8 }9 {10 id = 11;11 name = "hao";12 System.out.println("你好:好");13 }14 publicPerson(){15 id = 12;16 name = "ni hao";17 }18 }19 public classMain {20 public static voidmain(String[] args) {21 Person p1 = newPerson();22 System.out.println(p1.id + "\n" +p1.name);23 }24 }

输出结果:

你好:你

你好:好

12

ni hao

① 可有对类的属性(静态和非静态)进行初始化操作

② 里面可以有输出语句

③ 属性赋值的顺序:默认初始化值--->显式初始化或者代码块初始化(此处看顺序位置)--->构造器--->通过setter方法

2)静态块

① 随着类的加载而加载,而且只被加载一次。

② 静态的代码块在非静态代码块之前运行

③ 非静态的属性不能放在静态代码块

笔试题:

1 classA{2 static{3 System.out.println("1");4 }5 {6 System.out.println("2");7 }8 publicA(){9 System.out.println("3");10 }11 }12 class B extendsA{13 static{14 System.out.println("a");15 }16 {17 System.out.println("b");18 }19 publicB(){20 System.out.println("c");21 }22 }23 public classMain {24 public static voidmain(String[] args) {25 A a = newB();26 a = newA();27 }28 }

输出结果:1 a 2 3bc23

总结:

① 不管是静态代码块还是非静态代码块都是从父类开始执行的。

② 静态代码块只执行一次,非静态代码块new一次执行一次。

抽象类:

1、抽象类

① 抽象类不能被实例化

② 抽象类可以有构造函数

③ 抽象方法所在的类一定是抽象类

④ 抽象类中可以没有抽象方法

⑤ 不能和final共同修饰类

2、抽象方法

① 抽象方法必须需要子类进行重写

② 抽象类中可以有具体的实现方法。

③ 若子类是一个具体的“实体类”,那么就必须实现继承抽象类中的所有的抽象方法

④ 若子类继承抽象类,没有重写完所有的抽象方法,那么此类必须也是一个抽象类

3、其他:abstract不能修饰属性、构造器、private、final、static

① abstract 不能修饰属性,因为子类的属性是无法重写父类属性的

② abstract 不能修饰构造器,因为构造器不能被重写

③ abctract 不能和private修饰,因为你本来就是想让子类进行重写的,private的话你还让子类怎么重写。

④ final就不用说了,它修饰的方法不能被重写。它两个本身就是矛盾的。

⑤ static的话,直接用类.方法调用时不合规的。

1 abstract classAnimal {2 publicAnimal(){3 //只要实例化子类,抽象类的构造器会被执行。

4 System.out.println("我是一个抽象动物");5 }6 public voidbreath(){7 //抽象类中可以有具体实现方法。可以通过实例化子类,再调用抽象类的方法。

8 System.out.println("动物都会呼吸");9 }10 public abstract voidcry();11 }12

13 class Cat extendsAnimal{14

15 @Override16 public voidcry() {17 System.out.println("猫叫:喵喵...");18 }19 }20

21 class Dog extendsAnimal{22

23 @Override24 public voidcry() {25 System.out.println("狗叫:汪汪...");26 }27

28 }29 public classMain {30 public static voidmain(String[] args) {31 Animal cat = newCat();32 cat.cry();33 }34 }

执行结果:

我是一个抽象动物

猫叫:喵喵...

接口

接口是一个特殊的抽象类,只有两个元素①常量 ②抽象方法

1、接口不需要写权限修饰符,肯定是public。

2、常量默认使用public static final修饰,方法默认使用public abstract修饰

3、接口既不能实例化,也不能有构造器

4、如果实现接口,那么就需要实现接口的所有抽象方法

5、接口之间可以多继承

6、类可以实现多个接口,但是需要实现这些接口所有的抽象方法。

1 public classDayStudy {2 public static voidmain(String[] args) {3 //1、第一个多态性。格式:接口 参数 = new 实现类()

4 Runner d = newDuck();5 test1(d);6 //2、第二个多态性。参数用接口类型,传入实现类,解耦

7 Duck d1 = newDuck();8 test1(d1);9 test2(d1);10 test3(d1);11 }12 public static voidtest1(Runner r ){13 r.run();14 }15 public static voidtest2(Swiner s ) {16 s.swin();17 }18 public static voidtest3(Flier f ) {19 f.fly();20 }21 }22 interfaceRunner{23 voidrun();24 }25 interfaceSwiner{26 voidswin();27 }28 interfaceFlier{29 voidfly();30 }31 class Duck implementsRunner,Swiner,Flier{32 @Override33 public voidrun() {34 System.out.println("会跑");35 }36 @Override37 public voidswin() {38 System.out.println("会下水游泳");39 }40 @Override41 public voidfly() {42 System.out.println("会飞");43 }44 }

接口匿名类 :接口 参数 = new 接口(){ 这里面具体把接口的抽象类实现 }

Runner r = newRunner(){

@overridepublic voidrun(){

system.out.printLn("匿名类");

}

}

这篇关于面向对象下知识点java_跟着刚哥梳理java知识点——面向对象(八)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/377807

相关文章

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

Java中List转Map的几种具体实现方式和特点

《Java中List转Map的几种具体实现方式和特点》:本文主要介绍几种常用的List转Map的方式,包括使用for循环遍历、Java8StreamAPI、ApacheCommonsCollect... 目录前言1、使用for循环遍历:2、Java8 Stream API:3、Apache Commons

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

Java CompletableFuture如何实现超时功能

《JavaCompletableFuture如何实现超时功能》:本文主要介绍实现超时功能的基本思路以及CompletableFuture(之后简称CF)是如何通过代码实现超时功能的,需要的... 目录基本思路CompletableFuture 的实现1. 基本实现流程2. 静态条件分析3. 内存泄露 bug

Java中Object类的常用方法小结

《Java中Object类的常用方法小结》JavaObject类是所有类的父类,位于java.lang包中,本文为大家整理了一些Object类的常用方法,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. public boolean equals(Object obj)2. public int ha

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插