面向对象
1. 概述
-
类
类是构造对象的蓝图或模板。类就是具备某些共同特征的实体的集合,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象。在面向对象的程序设计语言中,类是对一类“事物”的属性与行为的抽象。
-
对象
所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念。
对象具有的三个特征:1. 行为 2. 状态 3. 标识
- 行为:可以对对象完成哪些操作,或者可以对对象引用哪些方法。
- 状态:调用那些方法时,对象会如何响应。
- 标识:如何区分具体相同行为和状态的不同对象。
-
类与对象的关系
类是对象的集合,对象是类的实例;对象是通过类产生的,用来调用类的方法;类的构造方法 .。
-
类与类的关系
-
依赖
即“uses-a”关系
简单的理解,依赖就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
-
聚合
即“has-a”关系
聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。
-
继承
即“is-a”关系
继承指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。
-
2.使用预定义类与用户自定义类
-
对象与对象变量
public class test { public static void main(String[] args) { //Date date; //String s=date.toString 此时date不是一个对象,也没有引用如何对象,不能再这个变量上使用任何Date方法 //必须首先初始化变量date,这有两个选择: //1.初始化这个变量,让他引用一个新构造器的对象 Date date1; date1=new Date(); //2.也可以设置这个变量,让他引用一个已有的对象 Date date; date=date1; System.out.println(date.toString()); System.out.println(date1.toString()); } }
输出结果如下:
Thu Sep 23 10:32:19 CST 2021 Thu Sep 23 10:32:19 CST 2021
-
构造器
类通过构造器实现对对象的实例化,构造器是一种特殊的方法,方法名与与类同名,没有返回值,连void都不能写.
构造方法可以重载(重载:方法名称相同,参数列表不同)
如果一个类中没有构造方法,那么编译器会为类加上一个默认的构造方法。
public 类名() { }
-
无参构造器
在创建类时, 默认创建隐式无参构造方法。
-
有参构造器
存在有参构造器,需要调用无参构造方法时,必须显示的写出无参构造方法,否则会编译报错。
-
-
隐式参数与显示参数
显式参数:显式参数是在方法中括号中声明的参数,例如:在这个方法中,n和a就是显式参数
隐式参数:隐式参数表示在方法中使用,但是没有写在方法参数中也没有在方法体内声明的变量(在类中声明的变量),例如:上边方法中的name和age两个变量就是隐式参数
public Employee(String n,int a){ super(); this.name = name; this.age = age; }
-
var声明局部变量
早先,所有的局部变量声明都要在左侧声明明确类型。 使用类型推断,一些显式类型可以替换为具有初始化值的局部变量保留类型var,这种作为局部变量类型 的var类型,是从初始化值的类型中推断出来的。
-
封装的优点
private封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
- 良好的封装能够减少耦合。
- 类内部的结构可以自由修改。
- 可以对成员变量进行更精确的控制。
- 隐藏信息,实现细节
-
更改器与改访问器
- 访问器:只访问对象不改变对象。
- 更改器:访问对象也改变对象。
3.静态字段与静态方法
-
静态字段
静态字段也称为类字段,它不属于任何一个对象。在类加载的时候,静态字段也被一同加载。对于非静态的实例字段,每个对象都有一个自己的副本。
-
静态方法
静态方法也称为类方法,它不属于任何一个对象。在类加载的时候,静态方法也被一同加载。
注:
-
静态方法只能访问静态字段和静态方法。
-
非静态方法不可以调用静态方法。
-
类可以调用任何静态字段和静态方法。
-
-
静态常量
final修饰的静态字段
-
静态代码块,匿名代码块,构造器加载顺序
public class StaticTest { //匿名代码块 { System.out.println("匿名代码块..."); } //静态代码块 static { System.out.println("静态代码块..."); } //构造器 public StaticTest() { super(); // TODO Auto-generated constructor stub System.out.println("构造器..."); } public static void main(String[] args) { StaticTest staticTest = new StaticTest(); System.out.println("==========="); StaticTest staticTest2 = new StaticTest(); } }
输出结果如下:
静态代码块... 匿名代码块... 构造器... =========== 匿名代码块... 构造器...
注:静态代码块只执行一次。
4.方法参数
程序设计语言中,将参数传递给方法(或函数)有两种方法。按值传递(call by value)表示方法接受的是调用者提供的值;按引用调用(call by reference)表示方法接受的是调用者提供的变量地址。Java程序设计语言都是采用按值传递。
public class ParamTest {
public static void main(String[] args) {
/*
*Test1: Methods can't modify numeric parameters
*/
System.out.println("Testing tripleValue:");
double percent = 10;
System.out.println("Before: percent=" + percent);
tripleValue(percent);
System.out.println("After: percent=" + percent);
/*
*Test2: Methods can change the state of object parameters
*/
System.out.println("\nTesting tripleSalary");
Employee harry = new Employee("Harry", 50000);
System.out.println("Before: salary=" + harry.getSalary());
tripleSalary(harry);
System.out.println("After: salary=" + harry.getSalary());
/*
*Test3: Methods can't attach new objects to object parameters
*/
System.out.println("\nTesting swap");
Employee a = new Employee("Alice", 30000);
Employee b = new Employee("Bob", 60000);
System.out.println("Before: a=" + a.getName());
System.out.println("Before: b=" + b.getName());
swap(a, b);
System.out.println("After: a=" + a.getName());
System.out.println("After: b=" + b.getName());
}
public static void tripleValue(double x) {
x *= 3;
System.out.println("End of method: x=" + x);
}
public static void tripleSalary(Employee x) {
x.raiseSalary(200);
System.out.println("End of method: salary=" + x.getSalary());
}
public static void swap(Employee x, Employee y) {
Employee temp = x;
x = y;
y = temp;
System.out.println("End of method: x=" + x.getName());
System.out.println("End of method: y=" + y.getName());
}
}
class Employee {
private String name;
private double salary;
public Employee(){}
public Employee(String name, double salary){
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public void raiseSalary(double byPercent){
double raise = salary * byPercent / 100;
salary += raise;
}
}
输出结果:
Testing tripleValue:
Before: percent=10.0
End of method: x=30.0
After: percent=10.0
Testing tripleSalary
Before: salary=50000.0
End of method: salary=150000.0
After: salary=150000.0
Testing swap
Before: a=Alice
Before: b=Bob
End of method: x=Bob
End of method: y=Alice
After: a=Alice
After: b=Bob
从以上例题可以总结Java中方法参数的使用情况:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
- 一个方法可以改变一个对象(数组)参数的状态。
- 一个方法不能让对象参数(数组)引用一个新的对象。
基本数据类型的传递:
- percent将值拷贝给x,percent与x的地址值不同;
- tripleValue()方法将x的值10乘以3后得到10,percent的值不变;
- tripleValue()弹栈后,参数变量x不再使用
对象或数组作为参数传递:
- Employee harry = new Employee(“Harry”, 50000); 创建了一个对象变量harry,引用了Employee的一个对象;
- tripleSalary(harry); 将对象harry的地址值传递给参数x, 此时变量harry和x都引用了堆中的同一个Employee对象;并通过方法将这一对象的薪金提高了200%;
- tripleSalary(harry)方法弹栈后,参数变量x不再使用。对象变量harry继续引用那个薪金增至3倍的对象。
5.对象构造
-
权限修饰符
权限大小:public > protect > default(默认) > private
public : 任何地方
protect :同一个类 , 同一个包 ,子类
default (默认) : 同一个类 , 同一个包
private:同一个类
-
无参构造
如果一个类没有编写构造器,就会为你提供一个无参构造器,如果在默认构造器中没有显示的初始化某些字段,那么会被自动的赋值为默认值:数值为:0,布尔为:false,引用对象为:null;
-
重载
方法名相同,返回值类型也相同,但是方法参数不同(包括参数个数,参数种类,参数顺序)。
public class Overloading { public int test(){ System.out.println("test1"); return 1; } public void test(int a){ System.out.println("test2"); } //以下两个参数类型顺序不同 public String test(int a,String s){ System.out.println("test3"); return "returntest3"; } public String test(String s,int a){ System.out.println("test4"); return "returntest4"; } public static void main(String[] args){ Overloading o = new Overloading(); System.out.println(o.test()); o.test(1); System.out.println(o.test(1,"test3")); System.out.println(o.test("test4",1)); }}
-
默认字段初始化
如果在默认构造器中没有显示的初始化某些字段,那么会被自动的赋值为默认值:数值为:0,布尔为:false,引用对象为:null;
-
调用另一个构造器
关键字this引用方法的隐式参数.然而,这个关键字还有另外一个含义.如果构造器的第一个语句形如this(…),这个构造器将调用同一个类的另一个构造器.
public class Constructer { public static void main(String[] args) { people p = new people("ming---"); }}class people{ private String name; private int age; public people(String name) { this(name,18); } public people(String name, int age) { super(); this.name = name; this.age = age; System.out.println(name+"---"+age); } }
输出结果:
ming------18