# Java基础之类和对象 **Repository Path**: fpfgitmy_admin/java-foundation-and-object ## Basic Information - **Project Name**: Java基础之类和对象 - **Description**: Java基础之类和对象介绍和使用 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-04-28 - **Last Updated**: 2021-04-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #### Java类及类的成员(属性、方法、构造器、代码块、内部类) ##### 面向对象(OOP Object Oriented Programming)与面向过程(POP Procedure Oriented Programming) + 面向对象是相对于面向过程而言的。面向过程,强调是功能行为,以函数/方法为最小单位,考虑怎么做。面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁 来做。 + 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。 + 方法定义时:`..`的区别 ##### 面向对象的三大特征(封装、继承、多态、抽象) + 封装(与隐藏):隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提供系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来,这就是封装性的设计思想。 + 封装性的体现:使用`private`关 键字对类的属性进行封装,并且使用`public`提供对外的`get、set`方法 + 单例模式 + 等等... + 多态:同一个行为(方法)有不同的表现形式。 + 体现:父类引用指向子类对象(在声明子类对象的时候返回父类引用) + 继承:使用`extends`关键字使子类继承父类的特征(属性)和行为(方法)。 ##### 权限修饰符的描述 | 修饰符 |类内部 |同一个包 |不同包的子类 | 同一个工程| | --- | --- | --- | --- | --- | | private | Yes | | | | | 缺省 | Yes | Yes | | | | protected | Yes | Yes | Yes | | | public | Yes | Yes | Yes | Yes| ##### 类和对象 + 类(Class)和对象(Object)是面向对象的核心概念 + 类是对一类事务的描述,数抽象的、概念上的定义 + 对象是实际存在的该类事务的每个个体,因而也称为实例(instance) + 类的创建如下 ``` public class Person { // 属性 String name; int age = 1; // 方法 public void eat(){ System.out.println("吃东西了"); } public void sleep(){ System.out.println("睡觉了"); } } ``` + 对象的创建如下 ``` public static void main(String[] args) { // 对象(实例)的创建 Person person = new Person(); // 方法的调用 person.eat(); person.sleep(); // 属性的调用 System.out.println("我今年"+ person.age + "岁了"); } ``` ##### 属性的使用(成员变量) | 名称 | 定义方式 |内存区别| | --- | --- |---| | 属性 | 定义在类的{}内 |加载到堆空间| | 局部变量 | 定义在方法内、方法行参、代码块内、构造形参、构造方法内 |加载到栈空间| ##### 方法的重载和重写 + 在同一个类中,允许存在一个或多个同名方法,只要它们的参数个数或参数类型不同即可 ##### 可变个数的形参 + JDK5.0采用可变个数形参来定义方法,传入零个或多个同一类型的变量 ``` public class Person { // 可变形参声明方式,参数为数组 public void test(String...val){ for (String item:val) { System.out.println(item); } }; public static void main(String[] args) { new Person().test("我","要","吃",”饭“); } } ``` ##### 构造器(Constructors) + 简单介绍:如果在创建类的时候没有显式的定义构造方法,则类会默认生成构造方法。 + 作用:可以自定义类的构造器,进行属性初始化操作。代码如下- ``` public class StudyClass {    private String name;    private String getName(){        return name;    }    public StudyClass(String name){ this.name = name;    }    public static void main(String[] args) {        StudyClass studyClass = new StudyClass("felix");        String name = studyClass.getName();     System.out.println("这是我初始化的名称="+name);    } } ``` #### 其他关键字(extends、this、super、static、final、abstract、interface、package、import、instanceof等) ##### `super`关键字的使用 + `super`调用属性、方法、构造器 ##### `this`关键字的使用 ##### `static`关键字的使用 + `static`描述:可以用来修饰属性、方法、代码块、内部类 ###### 修饰属性: + 简述:被`static`修饰的变量分为静态变量(只能修饰全局变量),又分为静态属性、非静态属性(实例变量),在创建对象的时候多个对象会共享同一个静态变量。 + 特点: 1. 静态变量随着类的加载而加载。可以通过 **类.静态变量** 的方式进行调用。 2. 静态变量的加载要早于对象的创建。 3. 由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中。 + 应用场景 1. 修饰常量或变量,用于初始化变量赋值,会生成在方法区内,占用内存,使用时效率更高 + 一些代码: ``` public class StudyClass {    private static int init = 1;    private int id;    public int getId() {        return id;    }    public void setId(int id) {    this.id = id;    }    public StudyClass() {       id = init++;    }        public static void main(String[] args) {  StudyClass studyClass = new StudyClass();        StudyClass studyClass1 = new StudyClass();        System.out.println(studyClass.getId());        System.out.println(studyClass1.getId());    } } ``` ###### 修饰方法 + 特点: 1. 随着类的加载而加载,可使用**类.方法**直接调用 2. 静态方法中只能调用静态的方法和属性(源自于自身的生命周期,静态方法在**类**初始化的时候已经被加载,而非静态方法在**对象**实例化的时候才会被加载到缓存区,对象消亡时非静态的方法会被释放)。 3. 不能使用`this`、`super`关键字(因为`this`和`super`指当前对象,对象需要实例化)。 + 如何判断是否要加`static` 1. 不变的且需要初始化的数据或方法 + 应用场景: 1. 工具类中的方法 2. 常量属性、需要被调用的静态方法 ###### 静态代码块 + 简述: + 应用场景:初始化一些配置文件的属性或配置值,代码如下 ##### `final`关键字的使用 + final 可以用来修饰类、方法、变量 + 修饰类 1. 不能被继承,比如String类、System类(为什么要设置不能被继承,因为父类已经有完整的方法和功能,继承并不能去进行扩充等操作) + 修饰方法 1. 表示方法不能被重写。(表明方法为最终方法) + 修饰变量 1. 用来修饰属性,此时的属性就成为一个常量,可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化------初始化请跳转[Java基础之属性赋值方式](https://www.jianshu.com/p/d030c6535e94) 2. 修饰局部变量:使用final修饰形参时,表明形参是一个常量,当我们调用此方法时,给常量形参一个实参,一旦赋值以后,就只能在方法体内使用此参,但不能重新赋值 ##### `abstract`关键字的使用 + abstract可以用来修饰类、方法,表示雷和方法时抽象的 + 修饰类 1. 类不能实例化 2. 抽象类中一定有构造器,便于子类实例化的时候调用(涉及,子类对象实例化的全过程) 3. 开发中,都会提供抽象类的子类,让子类去进行实例化 4. 如果类中有抽象方法,那么这个类一个是个抽象类 5. 被子类继承的抽象类,子类必须实现抽象类的抽象方法 + 修饰方法 1. 修饰方法时,添加abstract关键字,并且没有方法体 2. 抽象类中不一定有抽象方法 + 注意点 1. abstract不能用来修饰属性、构造器、代码块等结构 2. abstract不能用来修饰私有方法、静态方法、final的方法、final的类 ##### `interface`关键字的使用 + 使用interface修饰的被称为接口,接口可以多继承 + 接口和类是并列的两个结构 + jdk8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法。 ##### `extends`关键字的使用 ##### `instanceof`判断对象是否是该类的实例 ##### 代码块 ##### 匿名对象 + 简述:声明类缺未声明对象的方式,往往包含多态的使用 + 代码如下: ``` Person p = new Person(){ @Override public void eat(){ } } ``` ##### 内部类 + 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又分为外部事物提供服务,那么整个内部的完整结构最好使用内部类 + 当一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类, + 内部类又分类成员内部类(在类中声明的类,又分为静态内部类和非静态内部类)、局部内部类(方法内、代码块内、构造器内) + 成员内部类: 1. 可以调用外部类的属性和方法,使用`外部类.this.属性或方法`进行调用 2. 作为外部类的成员可以被4种修饰符修饰 3. 如何实例化静态成员内部类的对象`new 外部类.内部类();` 4. 如何实例化非静态的成员内部类`外部类类 p = new 外部类(); p.new 内部类();` 5. 内部类和外部类有同名方法或属性下如何调用,`this.属性、外部类.this.属性` + 局部内部类: 1. 在局部内部类的方法中的所声明的局部变量会是一个final类型的 ``` public Comparable getComparable() { // 标准方式一 /*class MyComparable implements Comparable { @Override public int compareTo(Object o) { return 0; } } return new MyComparable();*/ // 方式二,匿名对象 return new Comparable() { @Override public int compareTo(Object o) { return 0; } }; } ``` #### 对象的内存解析 + 内存解析如图 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0428/104025_a9029c94_1942182.png "屏幕截图.png") + 本地方法栈:通常调用本地方法c或者c++的方法 + 堆(heap),此内存区域的唯一目的就是存放对象实例,几乎所有的实例都在这里分配内存。 + 方法区:用于存储已被虚拟机家在的**类信息、敞亮、静态变量、即时编译器遍以后的代码**等。 + 虚拟机栈(stack):存储局部变量、对象实例的变量(包含了对象引用的地址)等,局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、short、long、int、double、float、char)、对象应用(reference类型),它不等同于对象本身,是对象在堆内存的首地址。方法执行完,自动释放 + 如下,对于对象引用的使用代码如下 ``` public static void main(String[] args) { // 对象(实例)的创建 Person p1 = new Person(); // 方法的使用 p1.eat(); p1.sleep(); p1.name = "tom"; // 属性的使用 System.out.println("我今年"+ p1.age + "岁了"); Person p3 = p1; // 只是改变了p3的地址=p1的地址 System.out.println(p3.equals(p1)); // 如果是对象比较的地址 p3.name = "fpf"; System.out.println("我用的是p1的堆地址:我的姓名"+ p1.name); // fpf System.out.println("我用的也是p1的堆地址:我的姓名"+ p3.name); // fpf } ``` #### 匿名对象 + 声明的对象没有赋值给变量,使用如下 ``` public class Person { // 属性 String name; int age = 1; // 方法 public void eat(String some){ System.out.println("吃东西了"+some); } public void sleep(){ System.out.println("睡觉了"); } public static void main(String[] args) { // 匿名对象的使用 new Person().eat("饭"); new Person().eat("面"); // 常见的匿名对象的使用 PersonMall mall = new PersonMall(); mall.show(new Person()); } } class PersonMall{ public void show(Person person){ person.sleep(); } } ```