- 面向过程:
- 步骤明确,第一、第二步…
- 适合处理一些简单的问题
- 面向对象:
- 分类的思维模式,先思考问题需要哪些分类,再对分类进行单独思考,最后,再对某个分类下的细节进行面向过程的处理
- 面向对象适合于多人协作的问题
- 面向对象编程的本质:以类的方式组织代码,以对象的形式封装数据
- 三大特性:
- 封装
- 继承
- 多态
- 类是对象的模板
- 静态方法
直接通过 类名.方法名 调用
//定义一个类,静态方法
public class Student{
public static void say(){
System.out.println("hello");
}
}
//main方法中
Student.say();
- 非静态方法
需要在main方法中实例化这个类,才能调用非静态方法;new
//定义一个类,非静态方法
public class Student{
public void say(){
System.out.println("hello");
}
}
//main方法中
Student student = new Student();
student.say();
注意:静态方法无法调用非静态方法
public class Demo01{
public static void main(String[] args){
}
//静态方法是和类一起加载的
public static void a(){
b(); //报错,因为b还没被实例化,该方法还不存在
}
//非静态方法需要实例化后才存在
public void b(){
}
}
- 形参和实参
在一般传值调用的机制中只能把实参传送给形参,而不能把形参的值反向地传送给实参。
public static void main(String[] args){
int a = 1;
System.out.println(a); //a=1
change(a); //a是实参
System.out.println(a); //a=1
System.out.println(change(a)); //a = 10
}
//change方法
public static void change(int a){ //a是形参
a = 10;
}
- 值传递和引用传递
值传递:
public static void main(String[] args){
int a = 1;
System.out.println(a); //a = 1
change(a);
System.out.println(a); //a = 1
}
//change 方法
public static void change(int a){
a = 10;
}
引用传递:
public static void main(String[] args){
Person person = new Person();
System.out.println(person.name); //null
change(person);
System.out.println(person.name); //曦曦
}
//定义一个方法
public static void change(Person person){
//修改的是person这个对象的值
person.name = "曦曦";
}
//定义一个Person类
class Person(){
String name;
}
三、对象的创建和分析
- 类跟对象的关系
- 类是一种抽象的数据类型,是对某一事物整体的描述或定义,但是并不能代表某一个具体的事物
- 对象是抽象概念的具体实例
- 创建与初始化对象
- 使用new关键字创建
//创建一个学生类; 类由属性和方法构成
public class Student{
String name; //属性
int age;
//方法
public void study(){
System.out.println(this.name +"正在学习");
}
}
- 使用new关键词创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。构造器具有以下两个特点
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
//当一个类即时什么都不写,也会存在一个方法
public class Person{
String name;
}
//在main方法中调用
public static void main(String[] args){
Person person = new Person(){};
//== Person person = new Person();
}
Person.java文件在编译成Person.class文件的时候会自动生成一个构造器,因为创建对象的时候必须要经过一个构造方法,若类中没有构造方法,则会默认一个无参构造
public Person(){} //构造方法
-
构造器:
- 无参构造
//作用:1.使用new关键字,本质就是在调用构造器 //2.用来初始化值 public Person(){ this.name = "曦曦"; //初始化值 }- 有参构造
public Person(String name){ this.name = name; } //或 public Person(String name,int age){ this.name = name; this.age = age; }
注意: 如果只有有参构造,要想通过无参构造创建对象的话,需要将无参构造显性写出来,因为写了有参构造后,无参构造就没办法默认生成
//main方法中
Person person = new Person();
//一旦有了有参构造,则无参构造必须显示定义
public Person(){}
public Person(String name){
this.name = name;
}
四、面向对象三大特性
1.封装
- 程序设计要追求“高内聚,低耦合”
- 高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合:仅暴露少量的方法给外部使用
- 封装(数据的隐藏)
- 禁止直接访问一个对象中数据的实际表示,应通过操作接口来访问,这称为信息的隐藏
- 私有属性,可以用get/set 获取、修改:
写一个学生类的属性私有public class Student{ //属性私有 private String name; private char sex; private int age; //在main方法中如果通过 对象名.name 等方式是无法访问到name,sex等属性的 //所以提供一些可以操作这个属性的方法,提供了一些get/set方法 //get:获得这个属性值 public String getName(){ return this.name; } //set:给这个属性设置值 public void setName(String name){ this.name = name; } public int getAge(){ return this.age; } //也可以用set做判断 public void setAge(int age){ if(age < 0 || age > 150){ this.age = 3; }else{ this.age = age; } }
}
```
//通过方法设置及访问类中的私有属性
public static void main(String[] args){
Student s1 = new Student();
s1.setName("曦曦");
System.out.println(s1.getName());
}
注意:可以使用 alt + Insert 自动生成get/set方法
意义:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护增加了
- 本质是对某一批类的抽象,从而实现对显示世界更好的建模
- extends,java中类只有单继承,没有多继承
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等
//person类
public class Person{
public int money = 10_0000_0000;
//如果money是private修饰的,则需要设置get/set方法来进行操作(封装)
public void say(){
System.out.println("说了一句话");
}
}
//继承Person类的Student类
public class Student exdents Person{
}
public static void main(String[] args){
Student student = new Student();
student.say();
System.out.println(student.money);
//通过访问可以把父类中的数据拿到
}
- object类是所有类的父类
- supper&this
父类:
public class Person{
//属性
protected String name = "曦曦";
//方法
//若改成private void print(){}的话,子类将无法继承该方法,super.print();就没办法调用
public void print(){
System.out.println("Person");
}
}
子类:
public class Student exdents Person{
private String name = "土豆";
public void print(){
System.out.println("Student");
}
//对子类和父类的方法的测试
public void test(){
print(); //Studnet
this.print(); //Student
super.print(); //Person
}
//对子类和父类的属性的测试
public void test1(String name){
System.out.println("name"); //土豆泥泥
System.out.println("this.name"); //土豆
System.out.println("super.name"); //曦曦
}
}
main方法
public class Application{
public static void main(String[] args){
Student student = new Student();
student.test();
student.test1("土豆泥泥");
}
}
构造器在子、父类直接的关系
父类:
public class Person{
public Person(){}
}
子类
public class Student extends Person{
public Student(){
//默认调用了父类的无参super();
System.out.println("调用了父类的无参构造");
}
}
若父类的构造器是有参构造
父类:
public class Person{
public Person(String name){
System.out.println("调用了父类的有参构造");
}
}
子类:
public class Student extends Person{
public Student(){
super(); //出错,因为无法调用父类的无参构造
//如果要正确调用,必须要用super("name"); 才可以,或者把无参构造显示化
System.out.println("调用了子类的无参构造");
}
}
注意:
- super调用父类构造器时,super()必须在子类构造器的第一排
- super必须只能出现在子类的方法或构造方法中
- super和this不能同时调用构造方法
一个构造函数中不能同时出现this和super两种方法,因为this函数中也有super,这会导致初始化两次,数据不安全
super&this
- 代表的对象不同:
this:本身调用者的这个对象
super:代表父类对象的应用 - 前提
this:没有继承也可以用
super:只有在继承条件下才可以使用 - 构造方法
this():本类的构造
super():父类的构造
- 方法的重写(重写都是方法的重写,和属性无关,非静态的方法才能进行重写)
static方法
父类:public class B{ public static void test(){ System.out.println("B=>test()"); } }
子类:
public class A extends B{
public static void test(){
System.out.println("A=>test()");
}
}
application:
//静态方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test(); //A=>test() B b = new A(); b.test(); //B=>test()
非static方法:
父类:
public class B{
public void test(){
System.out.println("B=>test()");
}
}
子类:
public class A extends B{
//override 重写
@Override //注解:有功能的注释
public void test(){
System.out.println("A=>test()");
}
}
application:
A a = new A(); a.test(); //A=>test() B b = new A(); b.test(); //A=>test()
原因: b是A new出来的对象,因此调用了A的方法,由于静态方法是类的方法,而非静态是对象的方法。有static时,b调用了B类的方法,因为b是用b类定义的,没有static时,b调用的是对象的方法,而b是用A类new出来的
注意:
重写:需要有继承关系,子类重写父类的方法
1. 方法名必须相同
2. 参数列表必须相同
3. 修饰符:范围可以扩大:public>protected>default>private
4. 抛出的异常:范围可以缩小,但不能扩大:
classNotFoundException --> Exception(大)
重写:子类的方法和父类必须要一致,方法体不同
为什么需要重写:
- 父类的功能,子类不一定需要,或者不一定满足
重写和重载:
- 重载是在一个类中的
- 重写是有继承关系的
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式
父类:
public class Pet{
public void run(){
System.out.println("run");
}
}
子类:
public Dog extends Pet{
public void run(){
System.out.println("跑得快");
}
}
public cat extends Pet{
public void run(){
System.out.println("跑得慢");
}
}
application:
public static void main(String[] args) {
Pet s2 = new Cat();
Pet s3 = new Dog();
s2.run(); //跑得慢
s3.run(); //跑得快
}
注意:
父类的引用指向子类时(用a表示),子类独有的方法a无法使用,但是父类所有的可用方法,子类都可以使用
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
- 多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意: - 多态是方法的多态,属性没有多态
- 是子类与父类之间的
- 不能被重写的方法
- static方法:属于类,它不属于实例
- final:常量
- private方法
引用类型,判断一个对象是什么类型:
System.out.println(x instanceof y);//能不能编译通过 //如果有继承关系就能编译,没有就编译错误 //通过编译后,再判断True或False //看x所指向的对象与y类是什么关系,如果x所指的对象的类比y类的高,则为False;如果x所指的对象的类别比y类的低(或等于),则为True;
例:
//object > Person > Student / Teacher object object = new Person(); System.out.println(object instanceof object); // true System.out.println(object instanceof Person); //true System.out.println(object instanceof Student);//False System.out.println(object instanceof Teacher);//False System.out.println(object instanceof String);//False5.父类与子类之间的强制类型转换
父类:
public class Person{
public void run(){
System.out.println("run");
}
}
子类:
public class Student{
public void run(){
System.out.println("跑得快");
}
public void go(){
System.out.println("go");
}
}
application1:
public static void main(String[] args){
Person obj = new Student();
obj.go(); //无法访问子类内部独有的方法,会报错
((Student)obj).go(); // 通过类型转化(向下转型),可以访问子类的独有的类
}
application2:
public static void main(String[] args){
Student student = new Student();
student.go(); //可以访问
Person person = student; //子类转换为父类
person.go(); //无法访问
((Student)person).go(); //强制类型转换,可以
}
总结:
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型(可能会丢失自己本来的一些方法)
- 把父类转换为子类,向下转型,强制转换
- 方便方法的调用,减少重复的代码,简洁
- 静态方法/属性
public class Student{
private static int age; //静态变量 多线程!
private double score; //非静态的变量
public void run(){ //非静态方法
}
public static void go(){ //静态方法
}
public static void main(String[] args){
go(); //可以直接调用
run(); //报错
//因为static方法属于类,非static方法是属于对象的
//所以要想调用非static方法(属性)必须new一个对象
Student student = new Student();
student.go();
student.run();
}
}
- 静态方法块
public class Student{
//匿名方法块:可用于赋初值
{ //第二
System.out.println("匿名方法块");
}
static {//第一
System.out.println("静态方法块");
}
public Student(){ //第三
System.out.println("构造方法");
}
public static void main(String[] args) {
Student student = new Student();
//新建一个对象时,三个方法的调用顺序:1.静态 2.匿名 3.构造
Student student1 = new Student();
//结果:1.匿名 2.构造
//因为静态方法与类一起加载,只加载一次
}
- 静态导入包
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Test{
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
//这样导入包后就可以直接通过方法名访问方法了。
//如果导入的是import java.lang.Math; :则需要通过Math.random(); 进行访问
- final
被final修饰的类,不能被继承



