Java教程

类与对象(Java)

本文主要是介绍类与对象(Java),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

类与对象

类(class)和对象(object)是两种以计算机为载体的计算机语言的合称。 对象是对客观事物的抽象,类是对对象的抽象。 类是一种抽象的数据类型。 它们的关系是,对象是类的实例,类是对象的模板。


对象:

1、新建一个对象

class Student {
	int score, id;
}
//直接创建
Student a = new Student();//新建一个Student对象空间,a指向这个空间,a又叫做对象引用/对象名
//先声明再创建
Student a;
a = new Student();
a.id = 1;
a.score = 100;

2、成员变量,int, double这些,也可以叫做属性/字段

成员变量可以是基本数据类型也可以是引用类型,如String

属性不赋值,会有默认值,机制和数组一样

3、访问修饰符:public,默认,protected,private

4、类是引用数据类型


方法重载:

特点:

只需要参数列表不同即可, 可以重名,返回类型无要求。


可变参数:

概念:

java允许讲一个类中多个同名但参数个数不同的写法封装成一个方法,用可变参数实现。

当参数数据类型都相同,且有多个的时候可以用可变参数来优化写法

基本语法:

基本修饰符  返回类型  方法名(其他数据类型,数据类型... 形参名){

}

例:

class test {
	public int getsum (int... n) {
		int res = 0;
		for (int i = 0; i < n.length; i ++) {
			res += n[i];
		}
		return res;
	}
}

细节:

1、可变参数的实惨个数可以是0个或任意多个

2、可变参数的实惨本质是数组

3、可变参数的实惨可以是数组

4、可变参数和普通参数放在形参列表时必须放在最后一个

5、一个形参列表只能出现一个可变参数


作用域:

全局变量/属性 可以被本类使用,或者其它类使用(通过对象的调用)

局部变量:只能在本类中对应的方法中使用

修饰符:

全局变量/属性可以加修饰符

局部变量不可以


构造器/构造方法

主要作用:

完成对新对象的初始化

特点:

1、方法名与类名相同

2、无返回值,也不能写void

3、创建对象时,系统会自动调用该类的构造器完成对对象的初始化

4、语法规则和成员方法一样

5、构造器可以重载,即多个构造器,形参列表不同

//例
class Yra {
	public static void main(String args[]) {
    	Person p1 = new Person("Tom", 18);	
	}    
}

class Person {
    String name;
    int age;
    public Person(String pname, int page) { //构造器初始化成员变量
        name = pname;
        age = page;
    }
}

PS:

1、如果没有定义构造器,系统会给类建立一个默认构造器;如果定义了就覆盖了默认构造器,且不能再使用,除非显式的定义一下,xxx () {}

//默认构造器
xxx() {

}

正如新建对象的时候 xxx a = new xxx();

这个后面的xxx()就是调用了默认构造器

技巧:

我们用javac xxx 编译好了xxx程序后,会新建一个xxx.class文件,java xxx指令可以用当前系统的解释器来运行程序,同时我们也可以改用javap xxx.class指令来反编译这个文件,我们就能得到被反编译后能看得懂的类的代码,.class可以省略

格式:javap < options > < classes >

-c 反汇编,-p 显示所有类和成员 ......


this关键字

解释:

在创建完一个对象后,Java虚拟机会给每个对象分配this,代表当前对象(相当于存了当前对象的地址,指向当前对象)

通过输出this的hashCode()和this所在对象的hashCode(),两者是一样的

补:

hashcode()可以返回该对象的哈希码值(一般是通过将该对象的内部地址转换成一个整数来实现的)

细节:

1、this关键字可以用来访问本类的属性、方法、构造器

2、this用于区分当前类的属性与局部变量

3访问成员方法的语法:

this.方法名(参数列表)

4、访问构造器的语法:(只能在构造器中使用,即只能在构造器中访问另一个构造器)

this(参数列表)

PS:如果要访问其他构造器,必须把这条语句放在该构造器的第一条语句

例:

public class Yra {
	public static void main(String[] args) {
		T a = new T();
	}
}
class T {
	public T() {
		//调用了下面这个构造器,形参列表要对应,同时要放在该构造器第一个语句
		this("Java", 18);
		...
	}
	public T(String s, int n) {}
}

5、this不能在类定义的外部使用,只能在类定义的方法中使用


包:

包可以将类打包,更好的管理类

1、区分相同名的类

2、控制访问范围

包基本语法:

package xxx.yyy //用来声明当前类所在的包,需要放在类的最上面,一个类中最多只有一个。

package是打包关键字,xxx.yyy是包名

可以用import xxx.yyy.类名引入类,这样可以直接用类名,否则需要前面加上包名

package xxx.yyy;
import xxx.yyy.wuhu;

...

wuhu a = new wuhu()
-------------------------或者

package xxx.yyy;
xxx.yyy.wuhu a = new xxx.yyy.wuhu();

import xxx.yyy.可以将xxx.yyy包下的所有类/工具导入

命名规则:

只包含数字、字母、下划线、小圆点,但不能数字开头,不能是关键字或保留字

命名规范:

一般是小写字母+小圆点

com.公司名.项目名.业务模块


访问修饰符:

image-20220302122259824

1、public: 对外公开

2、protected:对子类合同一个包中的类公开

3、默认级别的:没有修饰符号,向同一个包的类公开

4、私有级别:用private修饰,只有类本身可以访问,不对外公开。

同一个类:都能访问

同一个包:public, protected, 默认 可以访问, private不能访问

不同包:只有public能访问

无论是否同一个包,那么子类可以访问protected的父类。

默认则只有在同一包时,子类可以访问父类

PS:

1、修饰符可以修饰属性,成员方法以及类

2、只有默认和public能修饰类

3、成员方法的访问规则和属于完全一样

封装(encapsulation):

概念:

把抽象出来的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。

封装的理解和好处:

1、隐藏实现细节、方法(连接数据库)

2、可以对数据进行验证,保证安全合理

封装的实现步骤:

1、将属性私有化private

2、提供一个公共public的set方法,用于对属性判断并赋值

public void setXxx(类型 参数名) {
	//加入数据验证的业务逻辑
	属性 = 参数名;
}

3、提供一个公共的get方法,用于获取属性的值

public 数据类型 getXxx() { //权限判断, Xxx某个属性
	return xx;
}

set函数和get函数的快捷键:alt + insert,选择setter 和 getter

set方法与构造器:

可以将set方法写在构造器内,这样依然可以达到验证保护的效果

xxx (String name, int age) {
	this.setName(name);
	this.setAge(age);
}

继承:

继承基本介绍:

继承可以解决代码复用。当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有子类则不需要重新定义,只需要通过extends来声明继承父类即可

大致示意图:

image-20220302110734254

基本语法:

class 子类 extends 父类 {
	...
}

(1)子类会自动拥有父类定义的属性和方法

(2)父类又叫超类,基类

(3)子类又叫派生类

好处:

1、代码复用性提高 2、代码扩展性和维护性提高了

细节:

1、子类继承了所有的属性和方法,但是私有private属 性和方法不能再子类直接访问,要通过父类提供的公共的方法去访问

2、子类必须调用父类的构造器,完成父类的初始化

3、当创建子类对象时,不管使用子类的哪个构造器,默认情况下都会先去调用父类的无参构造器。如果父类没有无参构造器(有有参构造器,无有参构造器就会有默认的无参构造器),则子类中的构造器中需要加上super(),去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过。

4、如果希望指定调用父类的某个构造器,则显式的调用一下:super(),调用无参构造器可以不写(不加super()默认调用无参构造器,如果无就会编译不通过)。

5、super()在使用时,需要放在子类构造器第一行,super只能在构造器中使用

6、由于super()和this()都必须放在第一行,所以不能共同存在于同一个构造器中

7、Java所有类都是Object类的子类,Object是所有类的基类

8、父类构造器的调用不限于直接父类,将一直往上追溯直到Object类(顶级父类)

9、子类最多只能继承一个父类(直接继承),即Java中是单继承机制

10、不能滥用继承,子类和父类间必须满足is - a的逻辑关系

继承机制:

1、返回信息时,会先看子类是否有该属性且可以访问,如果有就返回,否则就看父类...直至Object类

PS:找的过程中只要遇到有,但不能访问(如private)就会报错,不会再向上访问。

super关键字:

概念:

super代表父类的引用,用于访问父类的属性、方法、构造器

注意点:

1、访问父类的属性,但不能访问父类的private属性

语法:super.属性名

2、访问父类的方法,不能访问父类的private方法

语法:super.方法名(参数列表)

3、访问父类的构造器,只能放在构造器的第一句,且只能有一句

语法:super(参数列表)

细节

1、调用父类构造器,能让分工更明确,父类属性由父类初始化,子类属性由子类初始化

2、当子类中有和父类中的成员重名是时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问,效果一样

[访问规则]:

先找本类,若有则调用,否则寻找父类的,如果找到了,并且可以访问就调用,否则继续访问父类的父类。

找到了但不能访问,则报错

没有找到,则提示方法不存在

方法cal()
cal();
this.cal();
super.cal();
三者区别在于super.cal()是直接查找父类

3、super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。

与this比较:

image-20220302200320641

方法重写/覆盖(override)

概念:

方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法。

细节:

1、子类方法的参数、方法名称,要和父类方法的参数、方法名称完全一样

2、子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类。

例:父类返回类型是Object,子类方法返回类型是String

3、子类方法不能缩小父类方法的访问权限,扩大可以

public > protected > 默认 > private


多态:

介绍:

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承之上的

1、方法的多态的体现:

方法重写、重载

2、对象的多态:

(1)一个对象的编译类型和运行类型可以不一致

例:

Animal animal = new Dog(); 【animal编译类型是Animal,运行类型是Dog】

animal = new Cat(); 【animal的运行类型变成了Cat,编译类型仍然是Animal

(2)编译类型在定义对象时,就确定了,不能改变

(3)运行类型是可以变化的

(4)编译类型看定义时 = 号的左边,运行类型看 = 号的右边

(5)查找属性时总是先看其编译类型,即属性不具备多态

3、细节:

前提:两个对象存在继承关系

向上转型

1、本质:父类的引用指向了子类的对象

2、语法:父类类型 引用名 = new 子类类型();

3、 特点:可以调用父类的所有成员,不能调用子类中特有成员(哪怕运行类型是该子类,但编译类型是父类的话也不能调用该子类的特有成员)

4、调用方法时,先从运行类型开始找,然后向上就近原则寻找方法。

向下转型

1、语法:子类类型 引用名 = (子类类型)父类引用

2、 只能强转父类的引用,不能强转父类的对象

3、要求父类的引用必须指向的是当前目标类型的对象(该引用的运行类型必须是目标类型)

4、当向下转型后,可以调用子类类型中的所有成员 ,否则不可以

属性没有重写之说,属性的值看编译的类型

判断一条语句是向上转型还是向下可以看等号右边的变量从什么类型变到什么类型,往父类变了就是向上,否则向下

4、instanceof

aa instanceof AA

判断aa的运行类型是否是AA类型或者AA类型的子类型

是则返回true,否则false

4、Java的动态绑定机制

1、当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

(在用a去调用某一个函数时,会一直从a的运行类型开始找,哪怕在A类里调用一个A类与A的子类都有的方法,这时候也会先从a的运行类型开始找,不会直接调用A类的该方法)

2、当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

(调用属性时则不同,在A类里调用一个A类和A的子类都有的属性,会直接调用A类的属性)

5、多态数组

多态数组中如果要调用各个元素的类型的特定方法,可以加上判断

if (a[i] instanceof A) {
	A的特定方法
} else if(a[i] instanceof B) {
    B的特定方法
}

Object类

一、equals方法

1、== 和 equals的区别

==:

即可以判断基本类 型(值是否相等),又可以判断引用类型(判断地址是否相等,即是否指向同一个对象)

equals:

是Object类中的方法,只能判断引用类型。Object的equals默认判断的是地址是否相等,子类里往往重写该方法,用于判断内容是否相等,例如Integer类,String类

String a = new String("wuhu");
String b = new String("wuhu");
System.out.print(a == b); // false 判断是否指向同一个对象
System.out.print(a.equals(b)); // true  重写为判断值是否相等

二、hashCode方法

1、提高具有哈希结构的容器的效率 HashSet、HashMap等

2、两个引用,如果指向的是同一个对象则哈希值肯定一样

3、两个引用,如果指向的是不同对象,则哈希值不一样

4、哈希值主要根据地址号来的,但不能完全相互等价

三、toString方法

1、默认返回:全类名(包名+类名)+ @ + 哈希值的十六进制

2、重写toString方法,输出对象属性时可以使用快捷键alt + insert --> toString

3、直接输出一个对象时,toString会被默认调用

四、finalize

1、当对象被回收时,系统会自动调用该对象的finalize方法(没有则会调用Object类的)。子类可以重写该方法,做一些释放资源的操作(比如数据库连接,或者打开文件…)。

2、什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法

3、垃圾回收机制的调用,是由系统来决定,也可以通过System.gc()主动触发垃圾回收机制

这篇关于类与对象(Java)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!