3.31~4.2学习总结

文章目录

目录

文章目录

一、包装类

二、处理对象

1.toString() 方法

2.== 和 equals()方法

 三、类成员

1.理解类成员

2.单例类

3.final关键字

1.Final 成员变量

2.final局部变量

3.final修饰形参:

4.final 修饰基本类型和引用类型的区别

 5.可执行"宏替换" 的final变量

6.final 方法

7.final 类

8.不可变类

9.缓存实例的不可变类

 四、抽象类

五、接口

 



一、包装类

3.31~4.2学习总结_第1张图片

包装类实现基本类型变量和字符串之间的转换:

利用包装类的 parseXxx (String s) 静态方法 (除Character之外的所有包装类都提供了该方法)

利用包装类的提供的 valueOf(String s) 静态方法

把基本类型变量转换成字符串 , 更为简便的方法是:  基本类型+""

如:    String str = 5 + "";

  • 自动装箱:基本数据类型自动转换成包装类。
  • 自动拆箱:包装类自动转换成基本数据类型。

3.31~4.2学习总结_第2张图片

数据缓存:

Java将一些创建成本大 , 需要频繁使用的对象缓存起来 , 从而提高程序的运行性能 

二、处理对象

1.toString() 方法

toString()是Object类中的一个实例方法,所有的java对象都具有toString()方法,这个方法是对象的自我描述方法。

该方法实现的功能 : 打印该对象的时候 , 系统将会输出该对象的 " 自我描述 " 的信息 , 用以告诉外界该对象具有的状态信息 

toString()方法是Object类里的一个实例方法
所有Java类都是Object类的子类
所有的Java对象都具有 toString()方法


所有的Java对象都可以和字符串进行连接运算
进行连接运算的时候,系统自动调用Java对象toString()方法的返回值和字符串进行连接运算

Object类提供的 toString() 方法总是返回该对象实现类的 "类名+@+hashCode"值

这个返回值不能真正实现"自我描述"的功能,需要重写Object类的 toString()方法
package process;

public class ToStringTest {
    public static void main(String [] args)
    {
        Apple a = new Apple("红色", 19.0);
        System.out.println(a);
    }
}
class Apple
{
    private String color;
    private double weight;
    //提供有参数的构造器
    public Apple(String color ,double weight)
    {
        this.color=color;
        this.weight=weight;
    }
    public void setColor(String name)
    {
        this.color = color;
    }
    public String getColor()
    {
        return this.color;
    }
    public void setWeight(double weight)
    {
        this.weight = weight;
    }
    public double getWeight()
    {
        return this.weight;
    }
    //重写Object类的toString()方法
    public String toString()
    {
        //return "一个苹果是,颜色是: " + color + ",重量是: " + weight;
        return "Apple[color="+ color + " , weight=" + weight + "]";
    }
}

2.== 和 equals()方法

 == 和 equals() 是用于判断两个值是否相等.
判定规则:

  • 如果两个变量是基本数值类型变量,则是判断两个变量只是否相等。

  • 如果两个变量是引用类型变量,只有它们指向的是同一个对象的时候,返回值才是true。

package process;

public class EqualTest {
    public static void main(String[] args)
    {
        int in = 65;
        float i = 65.0f;
        System.out.println("65和65.0是否相等?" + (in == i));
        char ch = 'A';
        System.out.println("65和'A'是否相等? " + (ch == in));
        String str1 = new String ("hello");
        String str2 = new String ("hello");
        //由于str1和str2都是引用变量类型,
        //他们通过两个关键字创建的String对象
        //因此str1和str2两个对象不相等
        //所以下面这行代码会输出false
        System.out.println("str1和str2是否相等? " + (str1 == str2));
        //由于String类重写了equals()
        //String类的equals()比较的是两个字符串的值
        //所以下面这行代码会输出 true
        System.out.println("str1和str2是否相等? " + (str1.equals(str2)) );
        //System.out.println("hello" == new EqualTEst());
        //JVM会先使用常量池来管理"1"直接量
        //再调用String类的构造器来创建一个新的String对象
        //新创建的String对象被保存在堆内存中
        //所以new String("1")创建了两个新字符串对象。
        //因为对象不同 所以下面的代码最终会输出 false 
        String str3 = new String ("1");
        System.out.println("str3和1是否相等? " + (str3 == "1" ));
    }
}

String类重写了equals(),String类的equals()比较的是两个字符串的值。 

常量池:
专门用于管理在编译时被确定并保存在已编译的 .class文件中的一些数据
它包括了关于类,方法,接口中的常量,还包括字符串常量

Object类的 equals()只是比较对象的地址
但是 equals()方法是可供重写的
即相等的条件完全由编写员决定

 三、类成员

1.理解类成员

  • static关键字修饰的成员就是类成员,有类变量,类方法,静态初始化块,静态内部类
  • static不能修饰构造器
  • 类成员属于整个类,而不属于某个对象

2.单例类

如果一个类始终只能创建一个实例,则这个类被称为单例类

package classmember;

public class SingletonTest {
    public static void main(String [] args)
    {
        Singleton a = Singleton.getInstance();
        Singleton b = Singleton.getInstance();
        System.out.println(a == b);
        /*
        通过封装的优势: 不允许自由访问类的成员变量和实现细节,
        而是通过方法来控制合适暴露
        从而保证Singleton类只能产生一个实例
        所以 , 在main()方法中,看到两次产生的Singleton对象实际上是同一个对象
         */
    }
}

class Singleton
{
    //使用一个类变量来缓存曾经创建的实例
    private static Singleton instance;
    //对该构造器使用private 修饰,隐藏构造器
    private Singleton(){};
    //提供一个静态方法 , 用于返回Singleton实例
    //该方法可以加入自定义 ,保证只产生一个Singleton 对象
    public static Singleton getInstance()
    {
        //如果instance为null ,表明还未创建过Singleton对象
        //反之,则已经创建过一个Singleton对象
        if(instance == null)
        {
            instance = new Singleton();
        }
        return instance;
    }
}
单例类:

在某些特殊的情况下,要求不允许自由创建该类的对象
这个时候就需要把该类的构造器使用 private 修饰,从而把该类的所有构造器隐藏起来


要隐藏该类的构造器,就需要通过一个公开的方法用于创建该类的对象,且该方法必须用static 修饰

该类还必须缓存已经创建的对象,否则该类无法知道是否曾经创建过对象
也就无法保证只创建一个对象

3.final关键字

final 关键字可以修饰类 , 变量 , 方法

它用于表示修饰的类 , 方法和变量不可变

  • final 可修饰成员变量 (类变量 , 实例变量) , 也可以修饰局部变量 , 形参
  • 被 final 修饰的变量不是不能赋值 , 而是 final 修饰的变量不可以被改变 
  • final 修饰的变量一旦获得了初始值 , 该变量就不能再重新被赋值

1.Final 成员变量

成员变量时随着类初始化或对象初始化而初始化的.

对于 final 修饰的成员变量而言 ,一旦有了初始值 , 其值就不能被重新赋值

如果成员变量指定初始值 , 也没有在初始化块 , 构造器中指定初始值 , 那么 这个 final 修饰的成员的变量值将全部为初始值 (比如 int 为 0 boolean 为false) 这个是没有意义的

所以规定: final 修饰的成员变量必须由程序员显式的指定初始值

package last;

public class FinalErrorTest {
    //定义一个final 变量
    //系统不会对final 变量进行默认初始化
    final int age ;
    {
        //age 没有初始化 下面代码将发生错误
        //System.out.println(age);
        //通过方法访问成员变量 这是合法的 输出 0
        PrintAge();
        age = 6;
        System.out.println(age);
    }
    public void PrintAge()
    {
        System.out.println(age);
    }
    public static void main(String [] args)
    {
        new FinalErrorTest();
    }
}

final 成员在写显示初始化之前不能被直接访问 , 但可以通过方法来访问

但是 , 按照正常逻辑 , final成员变量在显式初始化之前是不允许被访问的

因此 , 要尽量避免在 final 成员变量显式初始化之前访问它

2.final局部变量

系统不会对局部变量初始化
局部变量必须由程序员显式初始化
因此使用final修饰局部变量时 , 既可以在定义时指定默认值 , 也可以不指定默认值

3.final修饰形参:

由系统根据传入的参数来完成初始化 , 使用 final 修饰的形参不能被赋值

4.final 修饰基本类型和引用类型的区别

final 修饰基本类型变量时,不能对基本类型变量重新赋值
对于引用类型变量而言,
final 只保证这个引用类型变量所引用的地址不会改变
即一直引用同一个对象

final 修饰的引用类型变量不能被重新赋值
但是可以改变引用类型变量所引用对象的内容
即final 修饰引用类型变量不能改变变量的地址,但是可以改变这个引用变量里面的值
package last;

import java.util.Arrays;

public class FinalReferenceTest {
    public static void main(String [] args)
    {
        //final 修饰数组变量 . arr是一个引用变量
        final int [] arr = {5,6,19,2};
        System.out.println(Arrays.toString(arr));
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        //对数组元素赋值 , 合法
        arr[2]=-6;
        //下面语句对arr 重新赋值 ,非法
        //arr=null;
        System.out.println(Arrays.toString(arr));
        final Person a = new Person(6);
        a.setAge(89);
        System.out.println(a.getAge());
        //下面语句重新对 p 重新赋值,不合法
        //p=null;
    }

}
class Person
{
    private int age;
    public Person(){};
    public Person(int age)
    {
        this.age=age;
    }
    public void setAge(int age)
    {
        this.age = age;
    }
    public int getAge()
    {
        return this.age;
    }
}

 5.可执行"宏替换" 的final变量

final 相当于一个直接量的三个条件:

  1. 使用final修饰符修饰
  2. 在定义该final 变量时指定了初始值
  3. 该初始值可以在编译时就被确定下来
final 修饰符的一个重要用途就是"宏变量" ,
当定义了一个final 变量并且为其指定了初始值 ,
那么这个初始值在一开始就确定了下来 
 那么这个 final 变量本质上就是一个 " 宏变量 "


"宏变量"的用途: 编译器会把程序中所有用到该变量的地方直接替换成该变量的值
package last;

public class FinalReplaceTest {
    public static void main(String [] args)
    {
        final int a = 5+2;
        final double b = 1.2/3;
        final String c = "疯狂" + "Java";
        final String d = "疯狂Java讲义: " + 99.0 ;
        final String f = "疯狂Java讲义: " + String.valueOf(99.0);
        System.out.println(d=="疯狂Java讲义: 99.0");
        System.out.println(f=="疯狂Java讲义: 99.0");
    }
}
/*

Java会使用常量池来管理曾经用过的字符串直接量 , 例如执行 String a = "java"之后
常量池就会缓存一个字符串"java" ;
如果程序再次执行 String b ="java"
系统将会让b 直接指向常量池中的 "java"字符串
因此 a==b 返回true;
 */

final 宏变量:

  1. 赋予的表达式是算术表达式
  2. 字符串连接运算 ( 即使这个字符串连接运算中包含隐式类型 (将数值转换为字符串) 转换

Java会用常量池来管理曾经用过的字符串直接量

  • 对于实例变量而言 , 既可以在定义该变量的时候赋予初始值,也可以在非静态初始化块 , 构造器中对它赋初始值 , 这三个地方指定初始值的效果基本一样
  • 对于 final 实例变量而言 , 只有在定义该变量时指定初始值才会有 " 宏变量 " 的效果

6.final 方法

final 修饰的方法不可以被重写 

不希望子类重写父类的某个方法 , 则可以提供 final 修饰该方法


对于一个private 方法,因为它仅仅在当前类中可见, 其子类无法访问该方法 , 所以子类肯定无法重写该方法

如果子类中定义一个与父类private方法 有相同方法名 相同形参列表 相同返回值列表的方法,这不是方法重写,而是重新定义了一个方法

'因此,即使使用 final 修饰符一个 private 访问权限的方法 , 依然可以在子类中定义于该方法有相同方法名 相同形参列表 相同返回值列表的方法,

//以下例子: 不是方法重写
public class Sub extends PrivateFinalMethodTest{
    public void test()
    {
        
    }
}
class PrivateFinalMethodTest
{
    private final void test()
    {
        
    }
}

final 修饰的方法仅仅是不能被重写 , 并不是不能被重载!!

package last;

public class FinalOverload {
    public final void test()
    {
        
    }
    public final void test(String str)
    {
        
    }
}

7.final 类

final 修饰的类不可以有子类

final修饰的类不可继承

8.不可变类

不可变类的意思是创建该类的实例后 , 该实例的实例变量是不可改变的

可变类: 该类的实例变量的值是可变的 , 大部分创建的都是可变类

Java 提供的 8 个包装类和 java.lang.String 类都是不可变类

package last;

public class Person {
    private final Name name;
    //保证Person类的对象的name 的 firstName 不会改变
    public Person (Name name)
    {
        this.name =name;
    }
    public Name getName()
    {
        return name;
    }
    public static void main(String [] args)
    {
        Name a = new Name("悟空","孙");
        Person b = new  Person(a);
        System.out.println(b.getName().getFirstName());
        a.setFirstName("八戒");
        System.out.println(b.getName().getSecondName());
    }
}
class Name {
    private String firstName;
    private String secondName;
    public Name(){}
    public Name(String firstName,String secondName)
    {
        this.firstName = firstName;
        this.secondName = secondName;
    }
    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }
    public String getFirstName()
    {
        return this.firstName;
    }
    public void setSecondName(String secondName)
    {
        this.secondName =secondName;
    }
    public String getSecondName()
    {
        return this.secondName;
    }
}

创建自定义的不可变类:

  1. 使用 private 和 final 修饰符来修饰该类的成员变量
  2. 提供带参数的构造器 ( 或者返回该实例的类方法 ) 用于根据传入参数来初始化类里的成员变量
  3. 仅为该类的成员变量提供setter方法 , 因为普通方法无法修改 final 修饰的成员变量
  4. 如果有必要 , 重写 Object 类的 hashCode() 和 equals ()方法

9.缓存实例的不可变类

不可变类的实例状态不可改变 , 可以很方便的被多个多想共享.

如果程序经常需要使用相同的不可变类实例 , 则应该考虑缓存这种不可变类的实例

package last;
//引用数组来作为一个缓存池

public class CacheImmutaleTest {
    public static void main(String [] args)
    {
         CacheImmutale c1= CacheImmutale.valueOf("hello");
         CacheImmutale c2 = CacheImmutale.valueOf("hello");
         System.out.println(c1==c2);
    }
}
class CacheImmutale
{
    private static int MAX_SIZE = 10;
    private static  CacheImmutale [] cache = new CacheImmutale[MAX_SIZE];
    private static int pos = 0;
    private final String name;
    private CacheImmutale(String name)
    {
        this.name = name;
    }
    public String getName()
    {
        return name;
    }
    public static CacheImmutale valueOf(String name)
    {
        for(int i=0;i

 四、抽象类

  • 抽象方法和抽象类必须使用 abstract 修饰符定义 
  • 有抽象方法的类只能被定义成抽象类 
  • 抽象类里可以没有抽象方法

抽象方法和抽象类规则:

1. 抽象类必须用 abstract 修饰 , 抽象方法也必须用 abstract 修饰符来修饰

抽象方法不能有方法体 ( 既不能有花括号 )

2. 抽象类不能被实例化!!!!!

无法使用 new 关键字来调用抽象类的构造器创建抽象类的实例

即使抽象类里不包含抽象方法 , 这个抽象类也不能创建实例

3.抽象类可以包换成员变量 \ 方法(普通方法和抽象方法都可以) 构造器

初始化块 内部类(接口 枚举)

抽象类的构造器不能用于创建实例 , 主要是用于被其子类调用

4. 含有抽象方法的类只能被定义成抽象类

  • 抽象方法:
  • 直接定义了一个抽象方法 ;
  • 继承了一个抽象父类 ,但没有完全实现父类包含的抽象方法
  • 实现了一个接口 ,但没有完全实现接口包含的抽象方法
package Abstract;

public abstract class Shape {
    public abstract double calPerimeter();
    private String color;
    public abstract String getType();
    public Shape(){}
    public Shape(String color)
    {
        System.out.println("执行Shape的构造器....");
        this.color =color;
    }
    public void setColor(String color)
    {
        this.color =color;
    }
    public String getColor()
    {
        return this.color;
    }
}

 

package Abstract;

public class Circle extends Shape{
    private double radius;
    public Circle(String color,double radius)
    {
        super(color);
        this.radius =radius;
    }
    public void setRadius(double radius)
    {
        this.radius = radius;
    }
    public double calPerimeter()
    {
        return 2*Math.PI*radius;
    }
    public String getType()
    {
        return getColor() + "   圆";
    }
    public static void main(String [ ]  args)
    {
        Shape a1=new Circle("黄色" ,3);
        System.out.println(a1.getType());
        System.out.println(a1.calPerimeter());
    }
}
抽象类: " 有失有得" , "得" 指的是抽象类多了一个能力 : 抽象类可以包含抽象方法
"失" 指的是抽象类失去了一个能力 : 抽象类不能创建实例


抽象类不能用于创建实例 , 只能当作父类被其他子类继承

抽象类的作用:

从多个具有相同特征的类抽象出一个抽象类: 以这个抽象类作为子类的模板 , 从而避免了子类设计的随意性

抽象类体现的就是一种模板模式的设计 , 抽象类作为多个子类的通用模板 , 子类在抽象类的基础上进行扩展 , 改造 , 但是子类总体上会大致保留抽象类的行为方式

模板模式简单规则:

  1. 抽象父类可以只定义需要使用的某些方法 , 把不能实现的部分抽象成抽象方法 , 留给其子类去实现
  2. 父类种可能包含需要调用其他系列方法的方法 , 这些方法既可以由父类实现,也可以有子类实现. 父类里提供的方法只是一个通用算法,其实现也许并不完全由自身实现,而必须依赖于其子类的辅助

五、接口

接口:多个类共同的公共的行为规范 , 这些行为是与外部交流的通道 , 这就意味着接口里通常是定义一组公用方法

定义接口使用 interface 关键字

接口定义:
1.修饰符可以时public 或者 省略,如果省略了public 访问控制符,则默认采用包权限访问控制符
即只有在相同包结构下才可以访问该接口
2.接口名应该与类名采取相同的命名规则
3.一个接口可以有多个父类接口,但是接口只能继承接口,不能继承类
package related;

public interface Output {
    int MAX_SIZE_LINE = 50;
    void out();
    void getData(String str);
    default void print(String...msg)
    {
        for(int i=0;i

接口定义:

  • 修饰符可以时public 或者 省略,如果省略了public 访问控制符,则默认采用包权限访问控制符
  • 即只有在相同包结构下才可以访问该接口
  • 接口名应该与类名采取相同的命名规则
  • 一个接口可以有多个父类接口,但是接口只能继承接口,不能继承类

接口定义的是一种规范:

  • 接口不能包含构造器和初始化块定义
  • 接口里可以包含成员变量 ( 只能是静态变量 ) ,方法(只能是抽象实例方法.类方法,默认方法或者私有方法) 内部类(包括内部接口,枚举)定义

接口里定义的是多个类共同的行为规范

因此接口里的常量 , 方法 ,内部类和内部枚举都是public 访问权限


Java9 为接口增加了一种新的私有方法 , 私有方法可以拥有方法体 ,但是不能用 defualt 修饰

私有方式可以是类方法 , 也可以是实例方法

接口里定义的静态常量: 他们是接口相关的 , 系统会自动为这些成员变量增加static 和 final 两个修饰符

接口里的成员变量总是用 public static final 修饰符来修饰

接口里没有构造器和初始化块 , 所以接口里定义的成员变量只能在定义时指定默认值

  • 接口里定义的方法只能是抽象方法 , 类方法 , 默认方法或者私有方法
  • 如果不是定义默认方法 , 类方法或者私有方法 ,系统将自动为普通方法增加 abstract 修饰符
  • 接口里的普通方法总是使用 public abstract 来修饰
  • 接口里的普通方法不能有方法体 (即没有花括号)
  • 类方法 , 默认方法 ,私有方法都必须由方法体(即有花括号)

接口里定义的内部类 , 内部接口 , 内部枚举默认都采用 public static 两个修饰符

不管定义时是否指定这两个修饰符 , 系统都会自动使用 public static 对它们进行修饰

类方法(用static 修饰)

默认方法(default修饰)

私有方法(private 修饰)

静态方法(private static 修饰)

接口里定义的成员变量只能是常量


默认方法必须使用 default 修饰 , 该方法不能使用 static 修饰

无论程序是否指定 , 默认方法总是使用 public 修饰

接口的默认方法就是实例方法

接口里的成员变量默认是使用 public static final 修饰的

因此及时另一个类处于不同的包下 , 也可以通过接口来访问接口里的成员变量

接口可以被当成一种特殊的类. 因此一个Java 源文件里面最多只能有一个 public 接口 , 如果一个 Java 源文件里定义了一个 public 接口 ,则该源文件的主文件名必须与该接口名相同


接口的继承

接口的继承和类的继承不一样 , 接口完全支持多继承 , 即一个接口可以有多个直接父接口

和类继承相似 , 子接口扩展某个父接口时 , 将会获得父接口里定义的所有抽象方法 常量

一个接口继承多个父接口时 , 多个父接口陪在 extends 关键字之后 , 多个父接口之间以英文逗号隔开

package related;

interface interfaceA {
    int a =5;
    void testA();
}
package related;

interface interfaceB {

        int b = 6;
        void testB();

}
package related;

interface interfaceC extends interfaceA , interfaceB
{
    int c =7;
    void testC();
}

 

package related;

public class InterfaceExtendsTest {
    public static void main(String [] args)
    {
        System.out.println(interfaceC.a);
        System.out.println(interfaceC.b);
        System.out.println(interfaceC.c);
    }
}

使用接口;

接口不能用于创建实例 , 但接口可以用于声明引用类型变量

接口的主要用途就是被实现类是实现

接口的用途:

  • 定义变量,也用于进行强制类型转换
  • 调用接口中定义的变量
  • 被其他可实现

一个类实现了一个或者多个接口之后 , 这个类必须完全实现这些接口里所定义的全部抽象方法 (也就是重写这些抽写方法)

否则 , 该类将保留从父接口中那里继承到的抽象方法 , 该类也必须定义为抽象类

一个类可以实现一个或者多个接口

继承使用extends 关键字,实现则使用 implements 关键字

让类实现接口需要在类定义后增加 implements

实现接口方法时 , 必须使用 public 访问修饰符 , 因为接口里的方法都是 public 的 ,而子类的重写父类方法访问权限时只能是更大或者相等 , 所以实现类的方法只能用 public 修饰

接口不能显式继承任何类 , 但是所有接口类型的引用变量都可以直接赋给 Object 类型的引用变量

接口和抽象类:

接口和抽象类都不能被实例化 , 它们都位于继承树的顶端 , 用于被其他类实现和继承

接口和抽象类都可以包含抽象方法 , 实现接口或继承抽象类的普通子类都必须实现这些抽象方法

  • 接口与接口之间是继承关系
  • 一个接口可以继承多个接口
  • 一个类可以实现多个接口

 

你可能感兴趣的:(学习,python,pandas)