5.面向对象高级进阶

面向对象高级进阶

一、内部类
1.内部类概述
  • 是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。

  • 场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类

  • 分类:成员内部类、局部内部类、局部内部类、匿名内部类

  • 创建对象的格式:

    外部类名.内部类名 对象名 = new 外部类(...).new 内部类(...);
                        
    Outer.Inner in =  new Outer().new  Inner();
    
2.成员内部类
2.1 概述
  • 就是类中的一个普通成员
public class Quter{
    
    //成员内部类
    
    public class Inner{
        
    }
}
  • 注意:JDK16之前,成员内部类中不能定义静态成员,JDK16开始也可以定义静态成员
2.2 创建对象的格式
外部类名.内部类名 对象名 = new 外部类(...).new 内部类(...)
    
Quter.Inner in = new Quter().new Inner();
2.3 成员内部类中访问其他成员的特点
  • 可以直接访问外部类中的实例成员、静态成员
  • 可以拿到当前外部类对象,格式:外部类名.this
public class Demo1 {
    public static void main(String[] args) {
        A a = new Demo1().new A();
        a.show();
    }
    public class A{
        public void show(){
            System.out.println("show");
        }
    }
}
3.静态内部类
3.1 概述
  • static修饰的内部类,属于外部类持有
public class Quter{
    //静态内部类
    public static class Inner{
        
    }
}
3.2 创建对象的格式
外部类名.内部类名 对象名 = new 外部类.内部类(...)

Quter.Inner i1 = new Quter.Inner();
3.3 静态内部类中访问外部类成员的特点
  • 可以直接访问外部类的静态成员,不可以访问外部类的实力成员
public class Demo {
    public static void main(String[] args) {
//        Outer o = new Outer();
//        Outer.Inner i1 = o.new Inner();
        Outer.Inner i1 = new Outer.Inner();
        System.out.println(i1.name);
        i1.show();
    }
}
4.局部内部类
  • 局部内部类是定义在在方法中、代码块中、构造器等执行体中
public class Test {    
    public static void main(String[] args) {      
        
    }    
    public static void go(){        
        class A{            
        }        
        abstract class B{            
        }                
        interface C{            
        }    
    }
}

5.匿名内部类
5.1 概述

就是一种特殊的局部内部类;所谓匿名:指的是程序员不需要为这个类声明名字

//创建一个Animal的匿名内部子类对象 
new Animal(){
    
    @Override   
    
    public void cry() {...}
    
};
5.2 特点
  • 匿名内部类本质就是一个子类,并会立即创建出一个子类对象
5.3 作用

用于更方便的创建一个子类对象

Inter i1 = new Inter() {
    
            @Override
    
            public void method() {
                
                System.out.println("接口");
                
            }
        };

        i1.method();
5.4 使用场景
  • 通常作为一个参数传输给方法
二、枚举
1.枚举类本质

就是一个只能对外提供指定个数对象的类

2.枚举类格式
修饰符 enum 枚举类名{       
    名称1 ,  名称2, ... ; 
    其他成员…
}
3.枚举类注意点
  • 枚举类中的第一行,只能写一些合法的标识符(名称),多个名称用逗号隔开。

  • 这些名称,本质是常量,每个常量都会记住枚举类的一个对象。

4.枚举类特点
public enum A{
    X , Y , Z;
}
//上面的代码等价于:
public final class A extends java.lang.Enum<A> {
    public static final A X = new A();
    public static final A Y = new A();
    public static final A Z = new A();
    public static A[] values();
    public static A valueOf(java.lang.String);
}
  • 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。

  • 枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象

  • 枚举都是最终类,不可以被继承。

  • 枚举类中,从第二行开始,可以定义类的其他各种成员。

  • 编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法

三、泛型
1.泛型概述
  • 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:) ,称为泛型类、泛型接口,泛型方法、它们统称为泛型。
  • 作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常
  • 本质:把具体的数据类型作为参数传给类型变量
2.泛型类
修饰符 class 类名<类型变量,类型变量, ...> {

}

在【创建对象】的时候才能确定创建类的 <类型>

注意:类型变量建议用大写英文字母,常用的有:E、T、K、V

3.泛型接口
修饰符 interface 类名<类型变量,类型变量, ...> {

}
方式一:指定接口的 <具体泛型>
    public class 实现类 implements 接口<具体泛型>{ }
	public class InterImpl implements Inter<String>{ 
    	public void show(String s){ }
    }
方式二:在创建-[泛型实现类]-对象的时候传入 <泛型>
    public class 实现类<泛型> implements 接口<泛型>{ }
	public class InterImpl<T> implements Inter<T>{ 
    	public void show(T t){ }
    }
4.泛型方法
修饰符 <类型变量,类型变量,…>  返回值类型 方法名(形参列表) { 

 }
public static <T> void test(T t){
    
}

一般情况下,会把静态方法定义为泛型方法

格式:

public static<T> 返回值类型 方法名(参数列表){
    
}
5.泛型上、下限
5.1 通配符

就是 “?” ,可以在“使用泛型”的时候代表一切类型; E T K V 是在定义泛型的时候使用

5.2 泛型上、下限
泛型上限:   ? extends Car:   ? 能接收的必须是Car或者其子类 。
    -- 可以传递指定类的对象或者子类对象
    
泛型下限:  ?  super Car?  能接收的必须是Car或者其父类。
    -- 可以传递指定类或者父类对象
6.泛型的擦除问题和注意事项
  • 泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这就是泛型擦除。

  • 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。

四、进阶:常用API
1.API概述
  • API(Application Programming interface):应用程序接口
  • 就是别人帮我们已经写好的程序,如:类、方法等,拿过来直接用
2.Object类[超类]

Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法

2.1 Object常用方法
方法名说明
public String toString()返回对象的字符串表示形式
public boolean equals(Object o)判断两个对象是否相等[地址值]
protected Object clone()对象克隆
2.2 Object clone()克隆
  1. clone()浅克隆
  • 拷贝出的新对象,与原对象中的数据一模一样(引用类型拷贝的只是地址)
  1. clone()深克隆
  • 对象中基本类型的数据直接拷贝
  • 对象中的字符串数据拷贝的还是地址
  • 对象中还包含的其他对象,不会拷贝地址,会创建新对象
package d4_api_object;

import java.util.Objects;

public class Student implements Cloneable{
    private String name;
    private int age;
    String[] hobby;

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }

    public Student() {
    }

    //重写 toString() 方法,默认的 toString() 方法输出的是 随机值
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //重写equal方法,比较两个对象的每个属性值 是否相容,返回值是 boolean类型
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;//判断两个值类型是否一致
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    //重写 clone() 方法,要想重写 clone() 方法,本类必须作为实现类去实现 Cloneable接口
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    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;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

//测试类
package d4_api_object;
public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1 = new Student("张三", 16);
        System.out.println(s1);

        Student s2 = new Student("张三", 16);
        System.out.println(s1.equals(s2));

        System.out.println("==========");
        Object s3 = s1.clone();
        System.out.println(s1 == s3);

        System.out.println("==========");
        String[] arr = s1.getHobby();

    }
}
3.Objects
3.1 Objects概述
  • 是一个工具类,提供了很多操作对象的静态方法给我们使用
3.2 Objects类常见方法
方法名说明
public static boolean equals(Object a, Object b)先做非空判断,再比较两个对象
(防止了空指针异常)
public static boolean isNull(Object obj)判断对象是否为 null,为null返回 true
public static boolean nonNull(Object obj)判断对象是否不为null,不为null则返回true
import java.util.Objects;

public class Demo1 {
    public static void main(String[] args) {
        String s1 = null;
        String s2 = "张三";
//        System.out.println(s1.equals(s2));报错,空指针异常

        System.out.println("=============");
		
        System.out.println(Objects.equals(s1,s2));
        System.out.println(Objects.isNull(s1));
    }
}
4.包装类
  • 包装类就是把基本的数据包装成对象
4.1 基本数据类型及其包装类
基本数据类型对应的包装类(引用数据类型)
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
booleanBoolean
4.2 包装类的装箱拆箱
  • 装箱:将基础类型的数据包装成封装类的对象
  • 拆箱:将包装类对象拆分为基础类型的数据
public class IntTest {
    public static void main(String[] args) {
        //装箱:将基础类型的数据包装成封装类的对象
        Integer i = Integer.valueOf(10);
        //拆箱:将包装类对象拆分为基础类型的数据
        int i2 = i.intValue();

        -- 自动装箱
        Integer i3 = 10; // <==> Integer i3 = Integer.valueof(10);
        -- 自动拆箱
        int i4 = i3 + 12;// <==> int i4 = i3.intValue() + 12;

        Integer i5 = i3 + 13;
        /*
        * 这行代码执行步骤:
        *   1.自动拆箱: i3.intValue()
        *   2.加: i3.intValue() + 13
        *   3.自动装箱: Integer i5 = Integer.valueof(i3.intValue() + 13)
         */
    }
}
  • String和int互转
public class IntToString {
    public static void main(String[] args) {
        //将int转换为 String
        //方式一:拼接空字符串
        int a = 10;
        String s1 = a + "";
        //方式二:toString()
        Integer i2 = a;
        String s2 = i2.toString();
        //方式三:valueOf()
        String s3 = String.valueOf(10);

        //将String转换为 int
        int i4 = Integer.parseInt("10");

        //注意
        int i5 = Integer.parseInt("a");//报错:NumberFormatException: For input string: "a"

        //Character 包装类没有 pareXxx()方法
    }
}
5.StringBuilder、StringBuffer
5.1 StringBuilder
  • 代表可变字符串对象,相当于是一个容器,它里面装的字符串是可以改变的,就是用来操作字符串

好处:StringBuilder比String更适合做字符串的修改操作,效率会更高,代码也会更简洁

方法:

构造器说明
public StringBuilder()创建一个空白的字符串对象,不包含任何内容
public StringBuilder(String str)创建一个指定字符串内容的可变字符串对象
方法名称说明
public StringBuilder append(任意类型)添加数据并返回StringBuilder对象本身
public StringBuilder reverse()将对象的内容反转
public int length()返回内容对象长度
public StringBuilder toString()通过toString()将StringBuilder转换为String

注意点:

  • 对于字符串相关的操作,如频繁的拼接、修改等,建议用StringBuidler,效率更高!
  • 注意:如果操作字符串较少,或者不需要操作,以及定义字符串变量,还是建议用String
5.2 StringBuffer
  • 用法和StringBuilder一样
5.3 两者区别

StringBuffer是线程安全的,效率低;StringBuilder是线程不安全的,效率高

既然 StringBuffer是线程安全的,它的所有公开方法都是同步的,StringBuilder 是没有对方法加锁同步的,所以毫无疑问,StringBuilder的性能要远大于StringBuffer

// “zhangsan”反转并转换为 String 输出
        System.out.println((new StringBuilder("zhangsan").reverse()).toString());
        // abccba 判断回文:
        System.out.println((new StringBuilder("abccba").reverse()).toString().equals("abccba"));

为什么对于字符串相关的操作,如频繁的拼接、修改等,建议用StringBuidler

  • String 是不可变字符串、频繁操作字符串会产生很多无用对象,性能差。

  • StringBuilder:是内容可变的字符串、拼接字符串性能好、代码优雅。

注意:如果操作字符串较少,或者不需要操作,以及定义字符串时,则用String

6.StringJoiner
6.1 StringJoiner概述
  • JDK8开始才有的,跟StringBuilder一样,也是用来操作字符串的,也可以看成是一个容器,创建之后里面的内容是可变的

好处:不仅能提高字符串的操作效率,并且在有些场景下使用它操作字符串,代码会更简洁

6.2 构造器、方法
构造器说明
public StringJoiner(间隔符号)创建一个StringJoiner对象,指定拼接时的间隔符号
public StringJoiner(间隔符号,开始符号,结束符号)创建一个StringJoniner对象,指定拼接时的间隔符号、开始符号、结束符号
方法名称说明
public StringJoiner add(添加的内容)添加数据,并返回对象本身
public int length()返回长度(字符出现的个数)
public String toString()返回一个字符串(拼接之后的结果)
import java.util.StringJoiner;
public class JoinerDemo {
    public static void main(String[] args) {
        int[] arr = {11,22,33,44};
        System.out.println(arrToString(arr));
    }
    public static String arrToString(int[] arr){
        //StringJoiner(间隔符号,开始符号,结束符号)
        StringJoiner joiner = new StringJoiner(",", "[", "]");
        for (int i = 0; i < arr.length; i++) {
            joiner.add(arr[i]+"");
        }
        System.out.println(joiner.length())// 输出 13
        return joiner.toString();
    }
}
  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
1. 面向对象编程(OOP) 面向对象编程是一种编程范式,它将代码封装在对象中,这些对象可以相互交互和通信。Python是一种面向对象编程语言,它支持类和对象的概念,以及封装、继承和多态等OOP特性。 2. 装饰器(Decorators) 装饰器是Python中的一种语法结构,它可以用来修改函数或类的行为,而无需修改它们的源代码。装饰器可以用于添加日志、缓存、权限检查等功能,使得代码更加简洁、可读和易于维护。 3. 生成器(Generators) 生成器是一种特殊的迭代器,它可以用来生成序列值而不是一次性生成整个序列。生成器可以节省内存空间,提高代码的性能和可读性。Python中的生成器可以使用yield关键字来实现。 4. 协程(Coroutines) 协程是一种轻量级的线程,它可以在单个线程中实现并发执行。协程可以用于处理IO密集型任务、事件驱动编程和异步编程等场景。Python中的协程可以使用async/await关键字来实现。 5. 元编程(Metaprogramming) 元编程是一种编程范式,它允许程序在运行时修改自身的行为和结构。Python中的元编程可以使用元类、装饰器和属性描述符等特性来实现。 6. 多线程编程(Multithreading) 多线程编程是一种并发编程的方式,它允许程序同时执行多个线程,从而提高代码的性能和并发性。Python中的多线程编程可以使用threading模块来实现。 7. 多进程编程(Multiprocessing) 多进程编程是一种并发编程的方式,它允许程序同时执行多个进程,从而提高代码的性能和并发性。Python中的多进程编程可以使用multiprocessing模块来实现。 8. 异常处理(Exception Handling) 异常处理是一种错误处理的方式,它允许程序在出现错误时进行恰当的处理,而不是崩溃或停止。Python中的异常处理可以使用try/except关键字来实现。 9. 函数式编程(Functional Programming) 函数式编程是一种编程范式,它强调函数的纯粹性、不可变性和透明性等特性。Python中的函数式编程可以使用lambda表达式、高阶函数和函数式工具模块等特性来实现。 10. 数据科学和机器学习(Data Science and Machine Learning) 数据科学和机器学习是Python中的两个重要应用领域,它们涉及到数据处理、数据分析、数据可视化、统计学、机器学习和深度学习等技术。Python中的数据科学和机器学习可以使用numpy、pandas、matplotlib、scikit-learn和tensorflow等库来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值