JavaSE_04_类和对象
目录
类与对象
类是一组具有相同特征的对象的抽象,类中定义了所有该类的对象所共同具备的属性和方法
对象是某个类的一个具体的实体,使用new关键字创建一个对象
类的定义
- 在一个源文件中,只可以存在一个主类(
public class
) - 类的命名使用有意义的大驼峰(第一个单词首字母大写,若类名为多个单词,每个单词首字母大写)单词命名法
- 成员变量未初始化,其值为对应数据类型的默认值。引用数据类型的默认值为null
- 定义类的时候,可以给成员变量初始化
- null在Java中表示“空引用”,使用null调用对象时会报NULL Pointer Exception
实例化对象
//Person是一个类Person per = new Person();//new person() 是在堆中开辟对象的过程,要使用该对象,需要借助它的引用,即per(per在栈中开辟),per保存的是new出来的对象的地址
类的方法既不存储在栈中,也不存储在堆中,有个专门的方法区存储该类的方法,该类的所有对象共同使用该类的方法。
static关键字
看见static,其修饰的东西和对象无关
static不能直接修饰一个外部类->编译出错
static可以修饰:
属性,称为类属性、类变量,所有对象共享
为什么要有static修饰的变量?
- 普通的成员变量必须通过该类的对象来访问,当一个成员变量被static关键字修饰,它就表示类的属性,该类的所有对象共享这个属性,所有对象的该属性值都一样。
static关键字修饰的属性在
JVM
的方法区中存储static修饰的属性,通过类名可以直接访问,当然也可以用类实例化的所有对象来访问(不推荐)
类中的所有方法都在方法区中存储,包括一些常量、静态变量
在Java中,能否在一个方法的内部定义静态变量?
不能!!! 在方法中定义的变量都属于局部变量(局部变量在使用前必须赋值,不存在默认值),存储在栈中,函数栈帧结束后,其内部的局部变量都被释放。静态变量是存储在方法区中
static 修饰的变量和 final修饰的变量有何区别?
final 修饰成员常量,在类中定义时必须初始化。为了节省不必要的空间浪费,在类中定义常量,一般都会使用全局常量 static final ,常量的命名规则是:所有字母全部大写,各个单词之间用下划线分隔。
class Person{static String country = "中国";}Person per = null;per.country是可以输出的 //per虽然没有保存指向一个实实在在对象的地址,但它已经被定义为Person类型的引用,在此处相当于Person.country,直接用类名来调用静态变量
方法,称为类方法,工具方法
为什么主方法是个静态方法?
主方法是程序入口,若主方法是成员方法,则调用它必须先产生类的对象,通过对象调用。但没进入程序就无从谈起产生对象
静态方法能否访问成员域(成员变量和成员方法)?
不能!! 静态方法不产生对象就可以调用,而成员域需要产生对象才能调用;
静态方法中只能调用静态方法或静态属性,static家族之间可以相互调用
成员方法能否访问静态属性和静态方法?
可以
共享的变量设计为静态变量
工具类的方法设计为静态方法,如Arrays提供的方法
代码块,称为静态代码块
内部类,称为静态内部类
面向对象三大特性
封装
封装是为了实现保护性和易用性
用private进行封装只是封装的一种
权限修饰符
按访问范围从小到大依次划分为:private < default(也称为包访问权限,不用写出来,缺省权限修饰符的时候就是default) < protected < public
public
被public修饰的内容,在当前项目中都是可见的,都是可以使用的
private
只在当前类的内部可见,出了其所在的类,外部是不可见被private修饰的内容的
private关键字不能修饰外部类
getter()和setter()接口
如果想在类的外部使用类内部的私有属性,使用类提供的getter()和setter()方法(getter()是读取,setter()是修改)
编码规范:Java类中所有成员变量一律使用private封装,并根据属性的实际情况对外提供setter()和getter()接口
所有引用数据类型判断其是否相等,使用 .equals()方法。如
String str1 = "qwer";String str2 = "wer";if(str1.equals(str2)){ System.out.println("相等");}else{ System.out.println("不相等");}//若要判断两个引用的对象是否相等,使用str1.equals(str2),返回值为boolean.其他引用类型比较是否相等都用.equals()方法。
补充
编译错误和运行时错误
编译错误是指程序运行不起来,语法有错误;
运行时错误是指语法校验通过,程序可以跑起来,倒是跑到某一行出错了(逻辑错误),比如数组越界异常、空指针异常等等。
public class Pvf{ static boolean Paddy; public static void main(String args[]){ System.out.println(Paddy); }}
继承
多态
构造方法
构造方法的作用就是产生对象,使用new关键字产生一个对象时,分为两个步骤:1、为对象在堆中开辟一块空间,空间大小由该类中成员变量的属性决定;2、调用对象的构造方法,为所有成员变量赋初始值。
语法规则
- 构造方法名称与类名称完全相同
- 构造方法没有返回值声明(不是void)
- 一个类中至少有一个构造方法,若没有显式定义,编译器会生成一个默认的无参构造方法。当类中手动定义了构造方法,默认的无参构造方法不再生成。
构造方法的重载
重载只可能是由于参数个数的不同
调用有参构造函数时,成员变量的赋值过程
无论有参构造函数还是无参构造函数,调用时分三步
- 将所有成员变量初始化为所属类型的默认值(这里是构造函数假设所有成员变量都没有初始值)
- 为了验证上述假设是否正确,先不执行构造函数代码块内部的内容,先回到定义成员变量的地方。对于有初始值的成员变量,则成员变量的值变为定义时设置的初始值;若该成员变量没有设置初始值,则此时的成员变量的值就是第一步中设置的默认值
- 这里再执行代码块里面的内容(无参构造函数的赋值过程只有1-2步),将有参构造函数传进来的参数值赋给对应的成员变量
注意事项
- 一个对象不能调用自己的构造方法!
- 构造方法是在产生对象时由
JVM
调用
this关键字
this关键字可以
调用当前对象的成员变量
在构造方法的形参和成员变量重名时,使用this.成员变量表示成员变量
调用当前对象的方法(调用普通成员方法;构造方法的相互调用)
调用成员方法:
在类中的一个成员方法中调用另一个成员方法,使用this.方法名(),不加this也可以运行,编译后会自动加上this
构造方法的相互调用:
若不同参数的构造方法之间出现了重复的内容,使用this(参数)调用其他构造方法。
- this调用其他构造方法必须放在此构造方法的首行
- this调用构造方法不能成"环"!你调我,我调你,进入死循环。
表示当前对象的引用
当前的属性或方法是哪个对象调用的,this就指代该对象
public class Test02 { static class Student{ private String name; public void whoAmI(){ System.out.println(this); } } public static void main(String[] args) { Student stu = new Student(); System.out.println(stu); stu.whoAmI(); }}//输出Test02$Student@1540e19dTest02$Student@1540e19d//1540e19d是stu的值,stu保存new出来的Student类的一个对象的模糊地址,即1540e19d是该对象的模糊地址(真实地址对程序员不可见)
代码块
使用{}括起来的代码称为代码块
根据定义的代码块的位置以及关键字的不同分为四种
普通代码块
定义在方法中,用{}括起来的代码块。
成员代码块(构造块)
直接定义在类中,不加任何修饰符的代码块。优先于构造方法执行,有几个对象产生就调用几次构造块。
静态代码块
定义在类中,使用static修饰的代码块。在类加载时执行一次,与产生多少对象无关。类只要一加载,静态块就首先被执行,且只执行一次。
类定义与类加载
public class Test03 { public static void main(String[] args) { System.out.println(Animal.age); //输出结果为 100 }}class Animal{ static int age = 10; static { age = 100; }}
Animal类在定义的时候,类变量age被保存到方法区中,age的初始值赋值过程发生在类加载时。类加载时,若类变量有初始值,先将其初始值赋给类变量,再执行静态块。
同步代码块(多线程)
匿名对象
new出来的对象,没有引用指向,使用一次后就被销毁。匿名对象常用于进行测试类中的某些功能。
toString
方法(注意大小写)
当一个引用类型的变量调用println()
打印,得到的是该变量保存的指向的对象的模糊地址,实际上我们需要得到的是该对象属性值,为此需要在类中实现对应的toString方法
static class Student{ private String name; private int age = 10; private String sex = "男"; public String toString(){ String ret = "name= "+name+", age= "+age+", sex= "+sex; return ret; } public Student(String sex){ this.sex = sex; }}public static void main(String[] args) {System.out.println(new Student()); //输出为:name= null, age= 10, sex= 男 System.out.println(new Student("女")); //输出为:name= null, age= 10, sex= 女}