面向对象(OOP
)的程序是由对象组成的,每个对象包含对用户公开的特定功能部分。程序中的很多对象来自标准库,还有一些是自定义的。究竟是自己构造对象,还是从外界购买对象完全取决于开发项目的预算和时间。但是, 从根本上说, 只要对象能够满足要求,就不必关心其功能的具体实现过程。在OOP
中,不必关心对象的具体实现,只要能够满足用户的需求即可。
面向对象注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来。简而言之面向对象就是用代码(类)来描述客观世界的事物的一种方式, 一个类主要包含一个事物的属性和行为。
【面向对象概念】:
1.面向对象是思考问题的一种思考方式,是一种思想。比如:概念与实例。理论与实践。名和实等等。
2.类就是一类对象的统称。对象就是这一类具体化的一个实例。
3.面向对象的好处:将复杂的事情变简单了,只要面对一个对象就行。
类就是一类对象的统称。对象就是这一类具体化的一个实例。
简单的例子:我们做月饼的模子就是一个类,而通过这个模子可以做出月饼,那么在这个例子当中,类就是那个模子,而月饼就是那个对象,所以月饼就是一个实体。一个模子可以实例化无数个对象。总的来说:类相当于一个模板,对象是由模板产生的样本。一个类,可以产生无数的对象。声明一个类就是创建一个新的数据类型,而类在 Java 中属于引用类型, Java
使用关键字 class
来声明类。
我们来看一下简单的声明一个类:
class Person{
//字段 属性 成员变量 定义在类的内部,方法的外部
//成员变量分为普通成员变量,静态成员变量
public String name;
public int age;
//成员方法
//成员方法分为普通成员方法和静态成员方法
public void eat(){
System.out.println(name +"正在吃饭");
}
public void sleep(){
System.out.println(name +"正在睡觉");
}
}
class
为定义类的关键字, Person
为类的名字,{}
中为类的主体。
类中的元素称为:成员属性
。类中的函数称为:成员方法
。
用类类型创建对象的过程,称为类的实例化。
举一个例子:
class Person{
public String name;
public int age;//成员属性 实例变量
//成员方法
//成员方法分为普通成员方法和静态成员方法
public void eat(){
//成员方法
System.out.println(name +"正在吃饭");
}
public void sleep(){
//成员方法
System.out.println(name +"正在睡觉");
}
}
public class Test01 {
public static void main(String[] args) {
Person person = new Person();//通过new实例化对象
person.name = "zhang";
person.age = 10;
System.out.println(person.name); //成员变量的访问需要通过对象的引用来访问
person.eat();//通过对象的引用调用方法
person.sleep();
//产生对象 实例化对象
Person person2 = new Person();//一个类可以实例化出多个对象
Person person3 = new Person()
}
总结:
new
关键字用于创建一个对象的实例..
来访问对象中的属性和方法.类的成员可以包含以下:字段、方法、代码块、内部类和接口等。
首先来看一下字段(成员变量):
在类中, 但是方法外部定义的变量. 这样的变量我们称为 “字段” 或 “属性” 或 “成员变量”。
对于一个对象的字段如果没有显式设置初始值, 那么会被设置一个默认的初值。
默认值规则:
0
.boolean
类型,默认值为false
.String, Array,
以及自定制类),默认值为null
.很多时候我们不希望字段使用默认值, 而是需要我们显式设定初值, 可以这样写:
class Person {
public String name = "张三";
public int age = 18;
}
null 在 Java 中为 “空引用”, 表示不引用任何对象. 类似于 C 语言中的空指针. 如果对 null 进行 .
操作就会引发异常.
public static void main2(String[] args) {
Person person = null;//代表这个引用不指向任何对象
Person person1 = new Person();
Person person3 = person1;//代表person3这个引用指向person1这个引用所指向的对象
person1 = new Person(); //一个引用不可以同时指向多个对象
person1 = new Person();
person1 = new Person();
}
方法用于描述一个对象的行为。
如2.2
例子中的eat方法和sleep方法,表示 Person
这个对象具有一个 “展示自我” 的行为.这样的eat
方法和sleep
方法是和 person
实例相关联的. 如果创建了其他实例, 那么eat
方法和sleep
方法的行为就会发生变化。
所有被static所修饰的方法或者属性,全部不依赖于对象.
Java静态属性和类相关, 和具体的实例无关. 换句话说, 同一个类的不同实例共用同一个静态属性.
class TestDemo{
public int a;
public static int count;
}
public class Main{
public static void main(String[] args) {
TestDemo t1 = new TestDemo();
t1.a++;
TestDemo.count++;
System.out.println(t1.a);
System.out.println(TestDemo.count);
System.out.println("============");
TestDemo t2 = new TestDemo();
t2.a++;
TestDemo.count++;
System.out.println(t2.a);
System.out.println(TestDemo.count);
}
}
输出结果:
1 1
============
1 2
count被static所修饰,所有类共享。且不属于对象,访问方式为:类名 . 属性
如果在任何方法上应用 static
关键字,此方法称为静态方法。
类名.静态的成员属性/方法
。public static void staticFunc() {
//在静态方法内部不可以调用普通方法,静态的方法不依赖于对象
System.out.println("static::func()");
}
public void eat(){
System.out.println(name + "正在吃");
}
public void print(){
staticFunc();
//在普通方法内部可以调用静态方法,但是不可以定义静态变量
System.out.println("姓名:" + name + ",年龄:" + age);
}
静态方法和实例无关, 而是和类相关. 因此这导致了两个情况:
this
和super
两个关键字不能在静态上下文中使用(this 是当前实例的引用, super是当前实例父类实例的引用, 也是和当前实例相关.使用static定义的代码块。一般用于初始化静态成员属性,后面在代码块处会详细解释。
private/ public
这两个关键字表示 “访问权限控制” .
被 public
修饰的成员变量或者成员方法, 可以直接被类的调用者使用.
被 private
修饰的成员变量或者成员方法, 不能被类的调用者使用.
换句话说, 类的使用者根本不需要知道, 也不需要关注一个类都有哪些 private
的成员. 从而让类调用者以更低的成本来使用类.
private
不光能修饰字段, 也能修饰方法,通常情况下我们会把字段设为 private
属性, 但是方法是否需要设为public
, 就需要视具体情形而定. 一般我们希望一个类只提供 “必要的” public
方法, 而不应该是把所有的方法都无脑设为public
.
当我们使用 private
来修饰字段的时候, 就无法直接使用这个字段了,此时如果需要获取或者修改这个 private
属性, 就需要使用 getter / setter
方法.
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
【注意】:
getName
即为 getter
方法, 表示获取这个成员的值.setName
即为 setter
方法, 表示设置这个成员的值.set
方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this
, 相当于自赋值. this
表示当前实例的引用.setter / getter
方法, 而是要根据实际情况决定提供哪种方法.构造方法是一种特殊方法, 使用关键字new实例化新对象时会被自动调用, 用于完成初始化操作.构造方法没有返回值。
new 执行过程:
语法规则:
1.方法名称必须与类名称相同.
2.构造方法没有返回值类型声明.
3.每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造.
【注意】:
class Person{
private String name;
private int age;
public Person(){
System.out.println("不带参数的构造方法");
}
public Person(String name,int age){
this.name = name;
System.out.println("带1个参数的构造方法");
}
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("带2个参数的构造方法");
}
public void show(){
System.out.println("name: "+name+" age: "+age);
}
}
public class Main{
public static void main(String[] args) {
Person p1 = new Person();//调用不带参数的构造函数,如果程序没有提供会调用不带参数的构造函数
p1.show();
Person p2 = new Person("zhangfei");//调用带有1个参数的构造函数
p2.show();
Person p3 = new Person("zhangfei",80);//调用带有2个参数的构造函数
p3.show();
}
}
this表示当前对象引用(注意不是当前对象). 可以借助 this 来访问对象的字段和方法
1、this.data 调用当前对象的属性
例:
public void setName(String name){
this.name = name;//this代表当前对象的引用
}
public String getName(){
return name;
}
2、this.func() 调用当前对象的方法
例:
public void eat(){
System.out.println(name + "正在吃");
}
public void print(){
this.eat();
staticFunc();
//在普通方法内部可以调用静态方法,但是不可以定义静态变量
System.out.println("姓名:" + name + ",年龄:" + age);
}
3、this()调用当前对象的其他构造方法,存放在构造函数当中! ! !
例:
public Person(){
this("name",12);//调用带2个参数的构造方法 this必须放到第一行
System.out.println("不带参数的构造方法");
}
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("带2个参数的构造方法");
}
输出结果:
带2个参数的构造方法
不带参数的构造方法
name 12
使用 {}
定义的一段代码.
根据代码块定义的位置以及关键字,又可分为以下四种:
1.普通代码块
2.构造块
3.静态块
4.同步代码块
class Person{
//普通成员变量,属于对象
private String name;
private int age;
//静态的成员变量不可以在方法中定义
public static int count = 10;//静态成员变量->类变量 放在方法区
{
this.age = 90;
System.out.println("实例代码块");
}
static {
//本质上来说初始化静态的东西
count = 99; //如果都是静态的情况下,那么和定义的顺序是有关系的
System.out.println("静态代码块");
}
public static void main5(String[] args) {
Person person1 = new Person();//静态代码块,实例代码块
System.out.println("==============");
Person person2 = new Person(); //实例代码块 静态代码块只会被执行一次
}
public static void main6(String[] args) {
System.out.println(Person.count);//不用实例化对象,静态代码块也能被执行,并且只被执行一次
}
静态代码块和实例代码块在类加载时被执行。
静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行。
静态代码块不用实例化对象,都可以被执行。
匿名只是表示没有名字的对象.
没有引用的对象称为匿名对象.
匿名对象只能在创建对象时使用.
如果一个对象只是用一次, 后面不需要用了, 可以考虑使用匿名对象
class Person {
private String name;
private int age;
public Person(String name,int age) {
this.age = age;
this.name = name;
}
public void show() {
System.out.println("name:"+name+" " + "age:"+age);
}
}
public class Main {
public static void main(String[] args) {
new Person("caocao",19).show();//通过匿名对象调用方法
}
}
// 执行结果
name:caocao age:19
在上面的四
中我们用到了show方法,其实我们可以用toString方法来实现:
@Override //重写
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
【注意】:
toString
方法会在 println
的时候被自动调用.toString
是 Object
类提供的方法, 我们自己创建的 Person
类默认继承自 Object
类, 可以重写 toString
方法实现我们自己版本的转换字符串方法.