JavaSE之类和对象
-
什么是面向对象?什么是面向过程?⏰
一件事可能会细化成很多小事,如果是每件小事都要自己去编代码实现,才能够完成整件事,我们可以称之为面向过程。
一件大事可以分为简单的几个模块,通过这几个简单模块的交互(可以理解为合作)就可以完成整件事,此时可以称为面向对象
-
针对面向对象要干三件事👶
- 找对象
- 创建对象
- 适用对象
-
对象从何而来?🌵
从类而来。类由关键字class修饰,类名统一使用大驼峰。
-
一个类里包含哪些东西?🗡
- 字段/属性/成员变量(类的内部,方法的外部)
- 方法/成员方法
class Person{ public String name; public int age; public void eat(){ System.out.println(name+"正在吃饭"); } }
-
有了类如何产生对象?🦅
由类产生对象的过程叫做实例化,如:Person per=new Person();
须知:由类产生对象的过程,类在此处扮演一种类型的角色,就像int a=10;中的int 那样,并且有类定义的变量为引用变量,故:per是一个引用变量。new为关键字,在堆中实例化了一个对象。当然per也可以像指针那样不指向任何的对象,即:Person per=null;
-
有了对象,如何去访问对象的成员?🤕
首先由类产生对象,类此时相当于一个“模板”,照着这个模板可以造出很多对象,针对对象成员的访问,要通过该对象的引用加一个**.**来访问。
-
如果定义类时,并没有对其成员进行初始化,那么在主函数中打印由该类实例化的对象的成员时,结果是什么?💎
基本数据类型 整型(byte/short/int/long)=0;浮点型(float/double)=0.0;字符型(char)=\u0000;布尔类型(boolean)=false 引用数据类型 字符串\数组\枚举\接口=null
-
变量是否被static修饰,有什么区别?🔨
类中的成员(字段或者方法)被static修饰后,那这个成员将和类的代码片段一起存进方法区,不和该对象的普通成员变量一起存在堆中,并不意味着对象就不能用(访问)这个静态成员变量(类变量)了哈!可以用,只不过对静态成员变量的修改是永久性的,上代码:
class Person{ public String name; public int a; public static int age; public void eat(){ System.out.println(name+"正在吃饭"); } } public class Main{ public static void main(String [] args){ Person per1=new Person(); per1.a++; per1.age++; System.out.println(per1.a); System.out.println(Person.age);//类变量,用类名作成员访问 System.out.println("============"); Person per2=new Person(); per2.a++; per2.age++; System.out.println(per2.a); System.out.println(Person.age);//类变量,用类名作成员访问 } } //打印结果: //1 //1 //========= //1 //2
-
针对存在static修饰类的成员的情况,有几个注意事项🌮
- static修饰的字段只能是类的内部,方法的外部,换句话说:static只能修饰成员变量,不可修饰局部变量。
- 普通成员方法内部可调用静态方法,静态方法只能调用静态方法,或者这样理解:对象的成员(在堆上),它既可以调用堆上的东西,也可以调用方法区的东西,因为堆上都有对象了,说明有类进行实例化了,那方法区必有这个类的代码片段啊。而静态的成员在方法区,它们只能调用方法区的东西(没有对象的情况下),那如果静态方法中出现了普通成员方法,此时没有对象,就调用不了啊!如果静态方法中想强行调用普通方法,那就只有实例化一个对象,再去调用那个普通成员方法。
- 因为JVM自动的把main()设置成了static形式,所以说不创建对象的情况下,我们要想是有其他类中的函数,只能使用现存于方法区的静态方法。这里有一个问题?为什么main()是静态的,可以这样回答:main()静不静态都可以,这取决于JVM。
-
针对一个类实例化的对象所对应的引用变量来说,有几个注意点🔞
- 该引用可不指向任何对象,即null
- 一个对象可以被多个引用指向
- 一个引用只能指向一个对象,若有多次指向,就看最后一次指向谁,就可以。
- 引用一定在栈上吗?上代码
class Person{
public String name;
public int age;
public static count;
public void eat(){
Syetem.out.println(name+"正在吃饭");
}
}
public class Main{
Person per=new Person();
public static void main(String [] args){
Main main=new Main();
}
}
//引用变量main在栈上,指向堆中的对象,该对象上来就是一个引用变量per,这个per又在堆新new了一个对象,此时就构成了引用不再堆上的情况。
5.一个对象存储到哪里,和它是否被final修饰没关系,final类似C中的const,只不过赋予一个变量常属性。存到哪里还是要看是不是static修饰。
-
重写🍢
我们常看到一个类实例化对象后,用sout对该对象的引用进行打印,其结果通常为引用所对应的类名再加一个@再加一个哈希值(暂时理解为经过处理的地址),为什么会这样,剖析源代码可以看出,sout打印出的东西,其实受一个函数String toString()的控制,只要在类中定义一个开放权限的(public)的toString(),我们就可以使sout一个引用打印出任何我们想打印的结果。
这里有一个快捷键:Alt+insert生成toString()即可。
-
封装📦
1.前面的代码中public一直未做解释,其实public是一个访问权限控制符,对应还有private或者什么都不写,这里先只介绍public和private。
2.public:“公开”,对谁公开?对类的调用者来说公开,也就是被public修饰了的成员,可以直接被类的调用者去通过引用去使用。
3.private:“私人的”,也就是不公开,类的调用者不可以直接使用private的东西。或者换句话说,被private修饰的成员,只能在所在类内使用。
4.存在的意义?
类的定义者改动代码,会使得类的调用者废很大劲改成一样的,否则代码错误。封装起来,只有定义者考虑代码的改动,封装了都会提供接口供调用者去使用(修改成员变量等),那你又会说,接口再被定义者改来改去咋办?一般不会这样🙆♂
-
针对封装的接口💛
getter和setter
上代码:
class Person{
private String name;
private int age;
public void setname(String name){
this.name=name;//this表示当前对象的引用
}
public void getname(){
return name;
}
}
public class Main{
public static void main(String[] args){
Person per=new Person();
per.setname("java");
String name=per.getname;
System.out.println(name);
}
}
那会有个问题,若一个类中有很多被private修饰的字段,定义者总不能针对每个字段都逐一去码代码提供接口吧?
这里就有快捷键:Alt+insert,或者右键→Getter and Setter→选择需要设置的字段接口就可以了。
-
构造方法🐎
-
概念:方法名与类名一致,无返回值
-
构造方法干嘛的?
对象的实例化必不可少的一步。
因为一个对象的产生需要两步:
- 为对象分配内存
- 调用合适的构造方法(构造方法可能不止一个)
-
new进行对象实例化的时候其实已经在调用构造方法了new Person();
-
构造方法即使我们不去定义它,编译器也会自动生成不带参数,也没有内容的构造方法,所以说一个对象的产生,必要有一步:调用合适的构造方法,我们没定义,它也要造一个去调用。
-
多个构造方法其实构成了方法的重载,那实例化对象的时候调用的到底是哪个构造方法(因为它们的名字都是一样的,都是类名),这要根据你new Person(参数),这里的参数情况,去调用参数情况一致的那个构造方法。
-
-
代码块☢️
- 本地代码块(普通代码块):定义在方法中的代码块,用的较少
- 实例代码块(构造代码块):定义在类中的代码块,一般用于初始化实例成员变量
- 静态代码块:使用static修饰的代码块,一般用于初始化静态成员属性
- 同步代码块:后续学习完多线程再谈
字段的初始化:
- 就地初始化:在类定义时就初始化了
- 使用构造方法初始化,上述已说
- 使用代码块初始化
注意事项:
- 静态代码块不管生成多少个对象,都只会执行一次,且是最先执行的
- 静态代码块执行完毕,执行实例代码块(构造代码块),然后才是构造函数
- 静态代码块即使不进行对象的实例化,也会被执行,而构造代码块只有在实例化时才会执行
- 即使静态代码块写在了实例代码块的后面,也是先执行静态代码块,再执行实例代码块
- 静态代码块只能修改静态成员,因为对象还没出来
-
匿名对象🍆
- 没有引用的对象称为匿名对象
- 匿名对象只能在创建对象时使用
- 如果对象知识用一次,后面不需要用了,可以考虑使用匿名对象