类和对象
- oop语言的三大特征?(OOP 面向对象的程序设计语言 Object-oriented-program)
继承 封装 多态 - 什么是类?什么是对象?
类是一类对象的统称,对象是类的具体化的实例。在现实世界中类就相当于设计图纸,而对象就是根据图纸建造出来的房子。 - 面向对象
关注对象 即参与过程所涉及到的主体 处理大问题 - 面向过程
关注过程 即整个过程中涉及的行为 处理小问题
类和类的实例化
A . 如何产生一个类
//产生类的语法
class 类名{
field;//成员字段 即类中的元素
method;//成员方法
}
比如
class Person{
//属性 成员变量 实例成员变量 存放在对象内
public String name;
public int age;
//static修饰的 静态成员变量(也叫类变量)编译时已产生 属于类本身且只有一份 放在方法区
public static int count = 10;
//被static和final同时修饰 静态常量 属于类本身 只有一份 后续不可更改 放在方法区
public static final int SIZE = 20;
//实例成员常量 被final修饰 也属于对象 放在哪个区不一定
public final int SIZE2 = 30;
//构造方法
public Person(String name,int age){
this.name=name;
this.age=age;
}
//实例成员方法
public void eat(){
System.out.println("吃饭");
}
//静态成员方法 不能访问非静态的成员
public static void staticTest(){
System.out.println("staticTest()");
}
}
类的作用是用来产生对象
B . 如何产生一个对象
对象就是类的实例化,所以产生对象就要用new实例化对象
用上方所建的Person类来举例
Person person=new Person();
person叫做对象的引用
可以用person.eat()
调用eat()
可以用person.name="代";
给name重新赋值
注意:
new
关键字用来创建一个对象的实例- 用
.
来访问对象中的属性和方法 - 一个类可以创建多个实例
类的成员
类的成员包含:字段,方法,代码块,内部类和接口等
A . 字段(field)
- 字段(成员变量):在类内部方法外部定义的变量,作用范围是整个类,可以看作是C语言中的全局变量
- 字段(成员变量)又分为:实例成员变量,静态成员变量(又叫类变量),常量
+ 实例成员变量:必须通过对象的引用来访问。如:person.name
+ 静态成员变量:被static关键字修饰,不建议用对象的引用(可以通过对象的引用访问,但是不建议person.count)来访问 一般用类名.属性 (Person.count)来访问
+ 常量:被final关键字修饰 - 对于一个对象的字段如果没有显式设置初始值,那么就会被设置一个默认的初值,默认值规则见下:
+ 对于各种数字类型,默认值为0
+ 对于boolean类型,默认值为false
+ 对于引用类型(String,数组,以及自定义类),默认值为null - 如果不希望字段使用默认值,则需要我么自行设置初值,可在类中对应字段直接赋值
B . 方法(method)
a) 方法:
用于描述一个对象的行为,如上方定义的Person类中的eat()方法
b) 构造方法
- 方法中还有一种特殊的方法称为构造方法,构造方法在使用new实例化对象时会被自动调用,其方法名和类名相同,用于对象的初始化
new执行过程(一个对象的产生)分两步:
- 为对象分配内存
- 调用合适的构造方法
注意:
- 构造方法方法名必须与类名相同,且没有返回值类型声明
- 一个类中至少有一个构造方法
- 如果在实现类的时候没有写构造方法 那么编译器会自动生成一个无参的构造方法,但是,如果自定义了一个不带参数的构造方法,那么编译器将不会为你自动生成不带有参数的构造方法
- 构造方法可以发生重载(函数名相同 参数不同 返回值不相同)
this关键字
我们会发现在构造函数的内部,我们可以使用this关键字,构造函数是用来构造对象的,此时对象还没有构造好,我们就使用了this,那this还代表当前对象吗?
当然不是,this代表的是当前对象的引用。
this使用注意事项:
- 静态方法内不能使用this
this.成员方法名
this.成员变量名
this() 调用构造方法 通过this调用另外一个构造方法时,必须放在第一行
C . static关键字
static的作用:
- 修饰属性
- 修饰方法
- 修饰代码块
在这里插入代码片
- 修饰类
此处重点讲修饰属性和方法,代码块的修饰见本文章”认识代码块“部分
使用static需要注意的事项:
- 所有被static所修饰的不管是方法还是成员 他的调用或访问都只需要通过类名就可以做到
也就是说 所有被static所修饰的不管是方法还是成员都不依赖于对象,属于类,只有一份,放在方法区
class HasStatic{
private static int x = 100;
public static void main(String args[ ]){
HasStatic hs1 = new HasStatic();
hs1.x++;
HasStatic hs2 = new HasStatic();
hs2.x++;
hs1=new HasStatic();
hs1.x++;
HasStatic.x--;
System.out.println( "x=" +x);
}
}
所以输出结果为x=102, static修饰的变量不依赖于对象,属于类变量,只有一份,后续的操作全都是针对于变量操作
-
又因为static不依赖于对象,所以被static修饰的上下文中不可以用this和super,一个是当前对象的引用,一个是当前实例父类的引用
-
这也就解释了main函数必须用static修饰的原因 否则就会陷入下面的矛盾 如果不是 那么main函数的调用需要对象
public class Demo{
public void main(String[] args){
Demo demo=new Demo;
Demo.main(...);
}
}
- 静态方法内部不允许访问非静态的数据成员
原因:静态方法不依赖对象,对象是否产生不影响调用静态方法
非静态要依赖对象,只有对象被实例化之后name才产生
封装
封装的目的在于让类调用者不必太多的了解类的实现者是如何实现类的,只要知道如何使用类就行了,降低了类使用者的学习和使用成本,从而降低复杂程度
A . private实现封装
private用法同public,表示访问权限控制
- private : 表示类私有的 只能在类内部访问,不能被类的调用者使用
- public : 表示公有,可以直接被类的调用者使用
B . 用getter()和setter()方法使用私有字段
1.初始化方式 给私有的设置set和get方法
class Person{
//属性 成员变量 实例成员变量 存放在对象内
private String name;
private int age;
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
注意:
getName
即为getter
方法, 表示获取这个成员的值.setName
即为setter
方法, 表示设置这个成员的值.- 当
set
方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this
, 相当于自赋值,this
表示当前实例的引用. - 不是所有的字段都一定要提供
setter / getter
方法, 而是要根据实际情况决定提供哪种方法.
字段 vs 属性
我们通常将类的数据成员称为字段(field),如果该字段同时提供了getter/setter
方法,那么我们也可以将它称为属性
代码块
- 字段的初始化方法有:
- 就地初始化
- 使用构造方法初始化
- 使用代码块初始化
- 什么是代码块:
用{}定义的一段代码
根据代码块定义的位置以及修饰代码块的关键字,可将代码块分为:- 普通代码块(本地代码块):定义在方法内的{}中的代码块
- 构造代码块(实例代码块):定义在类内部的{}中,一般用来初始化实例数据成员 实例代码块先于构造方法执行 和顺序无关
- 静态代码块:用static修饰的代码块,一般用于初始化静态数据成员 静态代码块先于实例代码块执行 两个都是static的则按顺序实行 静态的只初始化一次 无论是代码块还是属性
- 同步代码块
class Person{
private String name;//实例成员变量
private int age;
private String sex;
private static int count = 0;//静态成员变量 由类共享数据 方法区
public Person(){
System.out.println("I am Person init()!");
}
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
//静态代码块
static {
count = 10;//只能访问静态数据成员
System.out.println("I am static init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();//静态代码块是否还会被执行?不会!静态代码块最先执行且只执行一次
}
}
所以,执行结果是什么呢?
来源:CSDN
作者:穿撒板儿的追风少女
链接:https://blog.csdn.net/qq_43360037/article/details/103280888