阿里开发规范强制规定@Transaction必须指定rollbackFor

【题解】【AcWing】3766. 二叉树的带权路径长度

  返回  

面向对象编程知识点总结

2021/7/20 23:02:13 浏览:

文章目录

    • 一、This关键字
    • 二、Static关键字
    • 三、代码块
    • 四、Package
    • 五、Import
    • 六、封装
    • 七、继承
    • 八、super关键字
    • 九、方法重写
    • 十、抽象类
    • 十一、抽象方法
    • 十二、final
    • 十三、Object类
    • 十四、对象的比较 ==&equals()
    • 十五、多态
    • 十六、接口 Interface
    • 十七、面向接口编程
    • 十八、内部类—成员内部类
    • 十九、内部类—静态内部类
    • 二十、内部类—匿名内部类
    • 二十一、内部类—方法内部类
    • 二十三、垃圾回收机制

一、This关键字

this的作用:

  • 表示当前对象本身
  • 准确的说,this表示当前对象的一个引用

普通方法中使用this:

  • 区分类成员属性和方法的形参
  • 调用当前对象的其他方法(可以省略)
  • 位置:任意

构造方法中使用this:

  • 使用this来调用其他方法
  • 位置:必须是第一条

注意:this不能用于static方法中

二、Static关键字

  • static声明成员变量:
    是为静态成员变量或类属性、类变量。
    属于该类的公用属性,属于类,被这个类的所有实例所共享,在类被载入时被显示初始化
    对于该类的所有对象来说,static成员变量只有一份,被该类的所有对象共享
    调用方式
类名.类属性
或
对象.类属性
  • static修饰方法:
    静态方法
    调用方式
类名.方法名

在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员

静态方法不能以任何方式引用this和supper关键字

package com.lxg.oop;
/*
* static:
*       修饰成员变量的时候,表示静态成员变量或者叫类变量
*           普通变量在使用的时候,必须要通过对象名进行调用
*           类变量或者静态变量可以使用对象名调用也可以使用类名进行调用
*       修饰方法的时候,表示静态方法或者叫类方法
*           普通方法在使用的时候,必须要通过对象名进行调用
*           类方法或者静态方法可以使用类名,也可以使用对象名
*       注意:
*           1、静态变量,在创建对象之前被初始化,或者说在类被载入之前进行初始化
*           2、静态变量被所有的对象共享,属于公共变量,对象和类都可以直接调用,但是推荐使用类来调用
*           3、成员变量放在堆中,而静态变量放在方法去中静态区
*           4、静态变量不能定义在静态方法中
*           5、静态方法可以在非静态方法中进行调用
*           6、静态方法中不能直接调用非静态方法
*           7、静态方法中不允许出现this调用
*           8、一般工具类中的方法定义为static
* */
public class StaticDemo {

    String name = "zhangsan";
    static int age = 10;

    public static void test(){
//        test2();
//        static int a = 10;
    }

    public void test2(){
        System.out.println("non-static");
    }
    public static void main(String[] args) {
//        StaticDemo staticDemo = new StaticDemo();
//        //使用对象进行调用
//        System.out.println(staticDemo.name);
//        System.out.println(staticDemo.age);//10
//
//        staticDemo.age = 20;
//        System.out.println(staticDemo.age);//20
//        System.out.println(StaticDemo.age);//20
//
//        StaticDemo.age = 30;
//        System.out.println(staticDemo.age);//30
//        System.out.println(StaticDemo.age);//30
//
//        StaticDemo staticDemo1= new StaticDemo();
//        System.out.println(staticDemo1.age);//30
        //使用类名调用
//        System.out.println(StaticDemo.name);
//        System.out.println(StaticDemo.age);

//        StaticDemo sd = new StaticDemo();
//        sd.test();
//        StaticDemo.test();
//        sd.test2();

        StaticDemo staticDemo = null;
        staticDemo.test2();

    }
}

三、代码块

**概念:**使用{}括起来的一段代码
分类: 根据位置可以分为以下几种

  • 普通代码块:直接在方法或语句中定义的代码块
  • 构造代码块:直接写在类中的代码块
  • 静态代码块:使用statica声明的代码块
  • 同步代码块:

静态初始化块

  • 如果希望加载后,对整个类进行某些初始化操作,可以使用static初始化块。
  • 类第一次被载入时先执行static代码块;类多次载入时,static代码块只执行一次;static经常用来进行statica变量的初始化。
  • 是在类初始化时执行,不是在创建对象时执行。
  • 静态初始化块中不能访问非statica成员。

四、Package

Why?

  • 解决类之间重名问题
  • 便于管理类:合适的类位于合适的包

How?

  • 放在类定义的第一句非注释语句。
package com.lxg.oop;

注意事项

  • 写项目都需要加包,不要使用默认包
  • com.gao和com.gao.car,这两个包没有包含关系,是两个完全独立的包,只是逻辑上看起来后者是前者的一部分。

JDK中的主要的包

  • java.lang
    包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。
  • java.awt
    包含了构成抽象窗口工具集的多个类
  • java.net
    包含执行与网络相关的操作类
  • java.io
    输入/输出类
  • java.util
    使用工具类,如定义系统特性,使用与日期日历相关的函数

五、Import

Why?

  • 引入其他包,方便使用里面的类
    怎么使用?
  • import java.util.Date;
  • import java.util.*; //导入该包下所有的类。会降低编译速度,但丌会降低运行速度。
    注意
    java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
    如果导入两个同名的类,只能用包名+类名来显示调用相关类:
    java.util.Date date = new java.util.Date();

import static

  • 静态导入的作用:用于导入指定类的静态属性
  • JDK5.0后增加
  • 如何使用:
import static java.lang.Math.*;//导入Math类所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
//然后,可以在程序中直接使用
System.out.println(PI);

六、封装

面向对象的三大特征之一:封装
概念: 将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
好处:

  • 只能通过规定的方法访问数据
  • 隐藏类的实现细节
  • 方便加入控制语句
  • 方便实现修改

隐藏/封装:

  • 隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提高系统的可扩展性、可维护性。
  • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉
  • 低耦合:仅暴露少量的方法给外部使用

封装的步骤:

  • 1、设置属性的可见性:设置为private
  • 2、创建共有的getter/setter方法:用于属性的读写
  • 3、在getter/setter方法中加入属性控制语句:对属性值的合法性进行判断

eg:

class Dog{
	private String name; //私有化属性,将其封装

    //提供getter&setter对属性进行操作
    public void setName(String name){
    	this.name = name;  
    }
    public String getName(){
		return name;
	}
}

面向对象三大特征:

  • 封装
  1. 对外隐藏某些属性和方法
  2. 对外公开某些属性和方法
  • 继承

    1.子类、父类
    2.子类可以继承父类提供的属性和方法
    3.子类可以提供自己单独的属性和方法

  • 多态
    为了适应需求的多种变化,使代码变得更加通用。
    访问控制符:

  • 成员变量&成员方法访问权限
    public 公共的 可被项目中所有的类访问
    protected 受保护的
    default 默认的 类本身,同一包中其他类、它的子类(同一个包及不同包中的子类)
    private 私有的 只能被类本身访问

  • 类访问权限
    public 可被同一项目中的所有类访问
    default/friendly 默认的/友好的 可被同一个包中的类访问

封装要点:

  • 类属性处理
  1. 一般使用private
  2. 提供get/set方法来访问相关属性,这些方法通常是public
  • 一些只用于本类的辅助性方法可以用private

七、继承

一张图了解继承
在这里插入图片描述
人属于脯乳动物,具有哺乳动物的特征,又具有人特有的特征,可以说人这个类继承了哺乳动物这个类,同理哺乳动物又继承了了动物这个类。

为什么使用继承
看下图中的两个类图有什么问题?
在这里插入图片描述上图中两个类图具有一部分重复的代码,分开定义两个类的话,就会重复写多余的代码。
使用继承优化后的类图如下:
在这里插入图片描述
继承

  • 类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
  • 提高代码的复用性
  • extends的意思是“扩展”。子类是父类的扩展
  • 超类、父类、基类、子类、派生类

如何使用继承
编写父类

class Pet{
	//公共的属性和方法
}

编写子类继承父类

/**
extends:继承的关键字
子类只能继承一个父类,java是单继承
*/
class Dog extends Pet{
	//子类特有的属性和方法
}

理解继承

  • 子类访问父类成员
  1. 访问父类构造方法
//使用super关键字,代替父类对象,
super()        
super(name)
  1. 访问父类属性
super.name
  1. 访问父类方法
super.print();
  • 子类可以继承父类的所有资源吗?
    不能被子类继承的父类资源
  • 访问修饰符总结
    访问修饰符总结
  • 多重继承关系的初始化顺序
    多重继承初始化顺序图
    在何处使用继承
  • 符合is-a关系的设计使用继承
  • 继承是代码重用的一种方式,将子类共有属性和行为放到父类中去

八、super关键字

  • super是直接父类对象的引用。
  • 可以通过super来访问父类中被子类覆盖的方法或属性。
  • 普通方法
    没有顺序限制。可以随便调用
  • 构造方法中
    任何类的构造函数中,若是构造函数的第一行没有显示的调用super,那么Java会默认调用super();作为父类的初始化函数

Code

public class Test{
	public static void main(String[] args){
		new ChildClass.f();
	}
}
class FatherClass {
 	public int value;
 	public void f(){
 		value = 100;
 		System.out.println("FatherClass.value="+value);
 	} 
 }
class ChildClass extends FatherClass {
 	public int value;
 	public void f() {
 		super.f(); 
 		value = 200;
 		System.out.println("ChildClass.value="+value);
 		System.out.println(value);
		 System.out.println(super.value);
 	} 
}

super小结

  • super只能出现在子类的方法和构造方法中
  • super调用构造方法时,只能是第一句
  • super和this不能同时出现在构造方法中
  • super不能访问父类的private成员
  • super和this都不能再static方法中

九、方法重写

方法重写

  • 在子类中可以根据需要对从基类中继承来的方法进行重写。
  • 重写方法必须和被重写方法具有相同方法名称、参数列表和返回
    类型。
  • 重写方法不能使用比被重写方法更严格的访问权限。(由于多态)

Code;

public class TestOverride { 	
	public static void main(String[] args) { 
		Animal animal = new Animal(); 
		animal.shout();
		Dog dog = new Dog(); 
		dog.shout();
	}
}
class Animal{ 
	void shout(){ 
		System.out.println("发出声音!");
	}
}
class Dog extends Animal { 
	void shout(){ 
		System.out.println("旺旺旺!");
	} 
}

小结

  • 构造方法会被重写吗?
    构造方法不能被继承,因此不能被重写
  • 方法重写规则
    1. 方法名相同
    2. 参数列表相同
    3. 返回值类型相同或者是其子类
    4. 访问权限不能严于父类
  • 方法重载与方法重写
    方法重载与重写对比图

十、抽象类

Java中使用抽象类,限制实例化

public abstract class Pet{ //使用abstract 关键字修饰类,就是抽象类
	//抽象类,不能实例化
}

十一、抽象方法

抽象方法

  • 使用abstract 关键字修饰的方法
  • 抽象方法没有方法体
  • 抽象方法必须定义在抽象类当中
  • 抽象方法必须在子类中被实现,除非子类是抽象类
public abstract void print();// 抽象方法,没有方法体

十二、final

  • final 修饰类,不能被其他类继承
  • final 修饰方法,不能被重写
  • final 修饰属性,属性值不能被修改,作为常量

Code:

//final 修饰类,不能被继承
public final class Penguin extends Pet{
	//final修饰属性,不能更改
    final String home = "南极";     
    public void setHome(String home){
		this.home = home;  //错误,不能再给home属性赋值
    }
    //final修饰方法,不能被重写
    public final void print(){
    	//...
    }
}

在这里插入图片描述

十三、Object类

  • Object类是所有类的父类,如果一个类没有使用extends显性的继承另外一个类,那么这个类就继承自Object类
public class Person{
}
//等同于
public class Person extends Object{
}

Object类的主要方法

  • toString()方法
  • equals()方法

十四、对象的比较 ==&equals()

==

  • 比较两个基本类型变量的值是否相等
  • 比较两个引用类型的值即内存地址是否相等,及是否指向同一对象

equals()

  • 两个对象的内是否一致

示例

  • object1.equals(object2) 如p1.equals(p2)
    1. 比较所指对象的内容是否一致
    2. 是比较两个对象,而非两个基本数据类型
  • object1 == object2 p1==p2
    1. 比较p1和p2的值即内存地址是否相等,即是否是指向同一对象
      自定义类必须重写equals(),否者其对象比较结果总是false

十五、多态

定义

  • 同一引用类型,使用不同的实例而执行不同的操作
  • 多态性是OOP中一个重要的特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有在执行过程中才会被决定而非在编译器间就决定了。能提高系统的灵活性和可扩展性。

多态条件

  • 继承
  • 方法重写
  • 向上转型

实现多态两种方式

  • 使用父类作为方法形参实现多态
  • 使用父类作为方法返回值实现多态

类型转换

  • 向上转型——子类转换为父类,自动类型转换
  • 向下转型——父类转换为子类,结合instanceof运算符进行强制类型转换

使用多态的好处

  • 可以减少代码量,提高代码的可扩展性和可维护性

引用变量的两种类型

  • 编译时类型——由声明时的类型决定
  • 运行时类型——由实际对应的对象类型决定

Code

public class TestPolym {
	public static void main(String[] args) {
		Animal animal = new Dog(); //向上可以自动转型
		System.out.println(animal.age); //属性调用时,仍然是基类的属性。属性没有多态!
		// animal.shout();
		animalCry(new Dog()); 
		//传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
		//如果没有多态,我们这里需要写很多重载的方法。如果增加一种动物,就需要重载一种动物的喊叫方法。非常麻烦。
 		//有了多态,只需要增加这个类继承Animal基类就可以了。
		animalCry(new Cat());
		Dog dog = (Dog) animal; //编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。
		dog.gnawBone();
		System.out.println(dog instanceof Animal); 
		System.out.println(animal instanceof Cat);
		System.out.println(animal instanceof Dog); 
	}
	static void animalCry(Animal a){
		a.shout();
	}
}


class Animal {
	int age=10;
	public void shout(){
 		System.out.println("叫了一声!");
	}
 }
class Dog extends Animal {
	int age=28;
	public void shout() {
 		System.out.println("旺旺旺!");
	}
	public void gnawBone(){
 		System.out.println(“我在啃骨头");
	} 
}
class Cat extends Animal {
	int age=18;
	public void shout() {
		System.out.println("喵喵喵喵!");
	}
}

引用数据类型的类型转换

  • 子类型转换为父类:自动转换
  1. 上转对象不能操作子类新增的成员变量和方法
  2. 上转对象可以操作子类继承或重写的成员变量和方法
  3. 如果重写了父类的某个方法,上转型对象调用该方法时,是调用的重写的方法
  • 夫类型转换为子类:强制转换
  1. 需要满足所转子类是父类的其中一类子类

十六、接口 Interface

接口特性

  • 接口不可以被实例化
  • 实现类必须实现接口的所有方法
  • 实现类可以实现多个接口
  • 接口中的变量默认都是public static final类型的

接口的定义

  • 使用关键字interface定义接口
//定义接口
public interface UsbInterface{
	//接口方法,默认是public abstract的,实现类必须重写所有接口方法
	void service();
}

public class UDisk Implements UsbInterface{
	//重写接口方法
	public void service(){
		System.out.println("链接USB接口,开始传输数据");
	}
}

接口表示一种能力,体现在接口的方法上

接口和抽象类的区别?

  • 接口是比抽象类还抽象的“抽象类”,可以更加规范的对子类进行约束。全面的专业的实现了:规范和具体实现的分离。
  • 接口就是规范,定义的是一组规则。

接口相关规则

  • 接口中所有方法都是抽象的
  • 接口中的成员默认都是public类型的,可以省略不写public关键字
  • 接口中变量默认用public static final 标识,所以接口中定义的变量就是全局静态变量。
  • 可以定义一个新接口,使用extends去继承一个已有的接口。
  • 可以定义一个类,用implements去实现一个接口中的所有方法
  • 可以定义一个抽象类,用implement去实现一个接口,并实现接口的方法

如何实现接口

  • 子类通过implements来实现接口中的规范
  • 接口不能创建实例,必须实现接口中所有的方法,并且这些方法只能是public的
  • Java的类只单继承,接口支持多继承

十七、面向接口编程

面向接口编程

  • 在程序设计时,关心实现类有何能力,而不关心具体实现
  • 面向接口的约定,而不考虑接口的具体实现
  • 接口是一种约定

十八、内部类—成员内部类

成员内部类

  • 把一个类定义在另一个类的内部成为内部类
class Outer{
	private String info="hello";

	//声明内部类
	class Inner{
		//....
    }
}

注意

  • 外部类不能直接使用内部类的成员和方法
  • 如果外部类和内部类具有相同的成员变量 ,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,需要使用关键字this
package com.lxg.oop;

/**
 * @author lxg
 * @description 内部类演示例子
 * @date 2021/7/19
 */
public class Outer { //外部类

    class Inner{ //内部类
        public void print(){
            System.out.println("hello world");
        }
    }

    public void show(){ //外部类方法
        new Inner().print(); //调用内部类的成员方法 
    }
}

在外部访问内部类

public static void main(String [] args){
	Outer out=new Outer();//创建外部类的对象
	Outer.Inner inner=out.new Inner();//创建内部类的对象
	inner.print();//访问内部类的方法
}


/*
如果主方法在外部类内部,则可以省略Outer
Inner inner=out.new Inner();
*/

十九、内部类—静态内部类

使用关键字static修饰的内部类就是静态内部类

class Outer//声明类
{
	private static String info="hello World";//声明私有属性
	static class Inner//声明静态内部类
	{
		public void print(){//打印输出的方法
			System.out.println(info);
		}
	}
	public static void main(String [] args){
		new Outer. Inner().print();//调用方法
	} 
}

使用static修饰的内部类不能访问非static的外部属性

二十、内部类—匿名内部类

定义内部类时不写名字的类,就是匿名内部类
应用场景

  • 只使用一次

二十一、内部类—方法内部类

方法内部类

  • 将内部类定义在外部类的方法中
    注意事项
  • 方法内部类不能再外部类的方法以外的地方使用,所以,方法内部类不能使用访问控制符和static修饰符,
    Code
package com.lxg.oop;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

/**
 * @author lxg
 * @description 内部类演示例子
 * @date 2021/7/19
 */
public class Outer { //外部类

    class Inner{ //内部类
        public void print(){
            System.out.println("hello world");
        }
    }

    public void show(){ //外部类方法
        new Inner().print(); //调用内部类的成员方法
    }

    public void function(){
        //定义方法内部类
        class Inner1{
            public void show(){
                System.out.println("我是方法内部类的方法");
            }
        }
        //在外部类的方法中使用方法内部类
        new Inner1().show();  //可以使用
    }
}

小结

  • 继承
  • 方法重写的规则
  • 抽象类和抽象方法
  • final修饰符
  • Object类
  • 内部类

二十三、垃圾回收机制

对象空间的分配

  • 使用new关键字创建对象即可
    对象空间的释放
  • 传统的C/C++语言,需要程序员负责回收已经分配的内存,属于显式回收垃圾,有以下缺点:
  1. 程序忘记即使回收时,从而导致内存泄漏,降低系统性能。
  2. 程序错误回收程序核心类库的内存,导致系统崩溃。
  • Java语言不需要程序员直接控制内存回收,是由JRE在后台自动回收不再使用的内存,称为垃圾回收机制(Garbage Collection)
  1. 可以提高编程效率
  2. 保护程序的完整性
  3. 其开销影响性能。Java虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。

垃圾回收机制的关键点

  • 垃圾回收机制只回收JVM堆内存里的对象空间
  • 对其他物理链接,比如数据库链接、输入流输出流、Socket链接无能为力。
  • 现在的JVM有多种垃圾回收算法,表现各异
  • 垃圾回收发生具有不可预知性,程序无法精准控制垃圾回收机制执行。
  • 可以将对象的引用设置为null,按时垃圾回收机制可以回收该对象。
  • 程序员可以用过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否会进行垃圾回收依然不确定。
  • 垃圾回收机制回收对象之前,总会调用它的finalize()方法,如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象。
  • 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制。

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号