Java学习(五)

java学习(五)

面向对象(下)

java基本数据类型包装类

[外链图片转存失败(img-vjIiNfPZ-1568981904775)(C:\Users\msi\AppData\Roaming\Typora\typora-user-images\1549177155001.png)]

通过这些包装类就可以实现引用传递基本类型参数,这些包装类可以直接与基本数据类型相互赋值

还可以通过包装类提供的

class.parseXxx(String s)//静态方法

Xxx(String s)//构造器

实现将字符串转换为数值

String类提供String.valueOf(class n)方法可以把基本类型变量转换为字符串

在8位补码表示范围(-128~127)以外的Integer包装类的两个对象即使数值相等,内存也不相等;相对的,补码表示范围以内的同数值的对象内存地址是相等的。因此,使用静态的compare方法来比较对应的基本类型的数值是否相等

有关Object类

  1. toString()方法

    java所有类继承自Object类,因此都具备toString()(可重写)等方法。

    Object类提供的toString()方法主要用于输出类或者对象的自我描述信息,默认返回该类的“类名+@+hashCode

  2. ==与equals()方法

    ==类似cpp中的用法,equals()(可重写)则专用于判断对象的值而非地址

单例类

  1. 构造函数用private修饰
  2. 定义一个public static方法(因为此类仅允许创建一个对象,且构造函数被private修饰,故只能用类的方法来创建对象)
  3. 定义一个private static成员变量用于缓存曾经创建过的实例(对象唯一)

final修饰符

  1. 变量

    final修饰的变量一旦赋了初始值就无法再次更改,因此final修饰的成员变量必须被显式指定初值

    实例变量:定义时、普通初始化块、构造函数(普通函数不能给final变量赋值)

    类变量:定义时、静态初始化块

    宏变量:在定义的时候就赋初值,直接被编译器编译为直接值

  2. 方法

    被修饰的方法不可重写,但是可以被重载

  3. 被修饰的类不可以被继承

valueOf()方法

该方法缓存一定范围内的对象,若新传入的值在缓冲区中已存在则不再生成新对象

抽象类

  1. abstract修饰

  2. 有抽象方法的类只能被定义为抽象类,而抽象类里面可以没有抽象方法

    抽象方法写法:public abstract void test();

  3. 抽象类不可实例化,但是含有构造器,其构造函数不可用于创建实例,主要是用于被子类调用,抽象类主要用于被子类继承

  4. abstractfinal是相对的,不可同时出现;abstract修饰的方法不能同时被private修饰,否则将使子类的继承变得毫无意义

  5. 主要优点是可以不用知晓具体类型进行强制类型转换,而是直接用抽象类的引用变量使用子类的方法(类似cpp的纯虚函数),比普通类更适合拿来做原型

    比如定义抽象类shape,用trianglecircle继承它,以此发挥多态的作用

java8接口

其内部所有的方法都是抽象方法,不能含有普通方法,但java8允许定义默认方法,可以提供方法实现。

格式如下

public/default interface iname extends f1,f2
{
    //instance definations(成员变量只能是静态常量)
    //abstract method definations
    //interior class、interface、enum definations(java8 之后)
    //default method or class method definations
}

有关接口的定义:

  1. 接口内部成员的访问控制修饰符为public或省略(自动添加public修饰符);
  2. 对于接口内部的常量,系统会自动添加staticfinal修饰符,即总是会自动变成public static final
  3. 对于内部的普通方法会自动添加abstract修饰符;
  4. 普通方法不可以有方法体(不能实现,因为是抽象的)、而类方法(static修饰)、默认方法(default修饰)必须有方法体(必须实现)
  5. 接口内部不含构造器和初始化块的定义
  6. 接口中的内部类、内部接口、内部枚举默认都采用public static修饰
  7. 和类一样,一个.java文件只能有一个public接口,且需要和.java文件名相同
  8. 如果匿名内部类所创建的接口实例只需要实现一个抽象方法,则该接口称为函数式接口

接口的继承:

  1. 接口支持多继承,如:interface iC extend iA, iB

接口使用:

  1. 接口不可实例化,但可以被实现类实现,一个类可以实现多个接口。(模拟多继承)

    如:class A extends parent_class_B implements interface_C, interface_B, ...

    这个实现必须实现接口内的所有抽象方法,方法的修饰符只能是public(因为接口的抽象方法是public

  2. 接口类型的引用变量可以直接赋值给Object类的引用变量(为了实现多继承下的多态),如

    interface A = new Class();

java内部类

特性如下:

  1. 更好的封装:同一个package的其他类无法访问该内部类。

  2. 访问private成员:内部类被视为外部类的成员,同一类的成员间可以相互访问,但外部类不能访问内部类的成员变量(外部不能查看内部细节)

  3. 匿名内部类:仅使用一次的内部类,通过new 父类构造器(parameter)或者 接口()来定义,并且必须实现其内部的所有抽象方法。(省略了extendsimplements关键字),他只有隐式默认构造器,无法传递参数。

  4. 额外的修饰符:privateprotectedstatic

  5. 编译会单独生成OuterClass$InnerClass.class文件


  6. 非静态内部类访问外部类:类的非静态内部类可以直接访问外部类的private的成员,其实例必须寄生在外部类的实例中,内部类实例保存有它所寄生的外部类对象的引用

    内部类访问同名的外部类实例变量的成员变量:外部类类名.this.成员变量名(编译器从内向外查找变量)

    非静态内部类中不能有任何静态声明

  7. 外部类访问非静态内部类:外部类需要显式创建非静态内部类对象来调用访问其实例成员。

  8. 在外部类以外的地方创建非静态内部类对象:OuterInstance.new InnerConstructor(),即:非静态内部类的构造器必须通过外部类对象来调用,因为寄生关系

    因此,当新的类继承非静态内部类时,必须先创建一个外部类对象并将该对象传入新的类的构造器中

    以下是其他类继承内部类,实例化对象的固定模板格式:

    class Out
    {
    	public Out()
    	{
    		
    	}
    	class In
    	{
    		public In(String msg)
    		{
    			System.out.println(msg);
    		}
    	}
    }
    public class SubClass extends Out.In
    {
    	public SubClass(Out out)
    	{
    		out.super("hello");
    		//必须用 “外部类.super()”这一形式,调用SubClass的父类Out.In来显式调用内部类的构造器
    	}
    	public static void main(String[] args)
    	{
    		Out out = new Out();
    		SubClass test = new SubClass(out);
    	}
    }
    
  9. static修饰的类为静态内部类,它属于外部类本身。(只能是内部类,外部类无法用static修饰)

    创建时,直接new 外部类名.内部类构造器即可(类似包空间

  10. 接口也能定义内部类,但只能是静态内部类(默认public static),实用意义不大。

  11. 若要在外部类的静态方法如public static void main(String args[])中,实例化非静态内部类对象,则需要先实例化外部类对象,再实例化非静态内部类对象,因为普通的内部类对象隐含地保存了一个引用,指向创建它的外围类对象。或者将非静态内部类改为静态内部类。


  12. 局部内部类:定义在方法中的内部类,不能用访问控制符和static修饰,仅在该方法内有效同一个类可以有不止一个局部内部类。生成的.class文件名为OuterClass$NInnerClass.class其中,N代表局部内部类的数字序号。

lambda表达式

本质是对函数式接口实例化的简化。

  1. 使用:

    主要作用是代替匿名内部类的语法,省略匿名内部类对象的创建代码,简化为只有一个->箭头函数。

    当箭头函数主体只有一句代码的时候,可以直接省略大括号。

    当函数只有一个参数时,可以省略参数的小括号。

    可以省略return。

  2. 限制:

    lambda表达式的得到的目标对象类型(编译时指定的对象类型)必须是明确的函数式接口。

    lambda表达式只能为函数式接口创建对象——即只能有一个方法。

    例如:

    @FunctionalInterface
    interface Converter{
        Integer convert(String from);
    }
    
    Converter converter1 = from -> Integer.valueOf(from);
    
    Integer val = converter1.convert("99");
    System.out.println(val);//输出int 99
    

    即利用lambda表达式返回得到了一个函数式接口的对象converter1。

  3. 高级特性:方法引用与构造器引用,前后参数一一对应。

    方法引用:

    1. 引用类方法:格式为类名::类方法

      根据上面的例子,有Converter converter1 = Integer::valueOf;

    2. 引用特定对象的实例方法:格式为特定对象::实例方法

      例如Converter converter2 = from -> "fkit.org".indexOf(from);可以简写为

      Converter converter2 = "fkit.org"::indexOf;

    3. 引用某类对象的实例方法:格式为类名::实例方法

      例子如下

      @FunctionalInterface
      interface MyTest
      {
          String test(String a, int b, int c);
      }
      
      MyTest mt = (a, b, c) -> a.substring(b, c);
      
      String str = mt.test("Java I Love you", 2, 9);
      

      可以替换为MyTest mt = String::substring;以达到相同的目的。

    4. 引用构造器:格式为类名::new

      例子如下

      @FunctionalInterface
      interface YourTest
      {
          JFrame win(String title);
      }
      
      YourTest yt = (String a) -> new JFrame(a);
      
      JFrame jf = yt.win("My window");
      

      可以替换为YourTest yt = JFrame::new;函数式接口内的抽象方法的参数会传递给类的相应构造器。

  4. lambda和匿名内部类的区别

    1. 匿名内部类可以为任意接口抽象类普通类创建实例,而lambda表达式只能为函数式接口创建实例
    2. 匿名内部类可以调用接口中的默认方法,而lambda表达式不允许

枚举类

enum关键字定义,enum关键字和classinterface地位相同

  1. 和普通类的区别

    1. 默认继承java.lang.Enum类,因此无法显式继承其他父类
    2. enum定义,非抽象的枚举类默认用final修饰,无法派生子类
    3. 枚举类的构造器只能是private修饰,可以省略不写
    4. 枚举类的实例必须在第一行显式列出,编译器自动添加public static final修饰
    5. 枚举类的实例只能是枚举值
    6. 枚举类可以定义抽象方法,编译器会自动为他加上abstract修饰符,但用户不能添加该修饰符(因为这样就无法写出方法的实现)并由他自己的不同枚举值实现这个方法,语法类似匿名内部类
  2. 访问、遍历方式

    使用foreach循环的时候,可以使用EnumClass.values()来迭代所有实例

    也可以直接用EnumClass.variable的形式,直接访问

  3. 枚举类通常应设置为不可变类,其成员变量不应该允许外部改变

    public enum Gender
    {
        MALE("男"),FEMALE("女");//此处枚举值,即枚举类实例将会调用privte的构造器
        private final String name;
        private Gender(String name)
        {
            this.name = name;
        }
        public String getName()
        {
            return this.name;
        }
    }
    
  4. 枚举类可以实现接口,且对于每个不同的枚举值,可以以不同形式实现接口内的方法

    interface GenderDesc
    {
        void info();
    }
    
    public enum Gender implements GenderDesc
    {
    	MALE("男")
    	{//大括号内实际上可以视为匿名内部类的类体
    		public void info()
    		{
    			System.out.println("For Male.");
    		}
    	},
    	FEMALE("女")
    	{
    		public void info()
    		{
    			System.out.println("For Female.");
    		}
    	};
    	...
    }
    

    可以看出语法类似匿名内部类

垃圾回收

  1. 只负责回收堆内存中的对象,不回收任何物理资源(数据库连接、网络IO等)

  2. 程序无法精准控制垃圾回收,只有当对象永久性失去引用才会在合适的时间被回收

  3. 垃圾回收之前总会调用对象的finalize方法,可以通过finalize方法使得对象重新获得引用

  4. 程序可以通过System.gc()以及Runtime对象的方法Runtime.getRuntime().gc()通知系统强制回收垃圾。

  5. 有关finalize方法:

    原则上永远不要主动调用某个对象的finalize方法,该方法是专门留给垃圾回收调用的;

    finalize不一定会被执行;

    JVM执行finalize出现异常的时候,垃圾回收机制不会报告异常,程序会继续执行

    Runtime.getRuntime.runFinalization()System.runFinalization()可以强制垃圾回收机制调用可恢复对象的finalize方法

  6. 对象的软、弱和虚引用:

    强引用:常见的引用方式,不可被垃圾回收

    软引用:空间不足时,可能被回收,对内存敏感的程序很常见

    弱引用:类似软引用,但优先级更低,只要启动了垃圾回收,就会被回收

    虚引用:类似于无引用,常用于跟踪垃圾回收状态

    当对象被回收后,其引用存在于引用队列

JAR包

好处:

  1. 安全,设置数字签名
  2. JAR包除了内部会多一个名为META-INF/MANIFEST.MF的清单文件以外,其他完全和ZIP完全相同

使用:

  1. 创建: jar cf xxx.jar xxx,将当前路径下的xxx路径下的全部内容压缩生成一个xxx.jar文件

    创建可运行的jar包:jar cvfe test.jar test.Test test,把当前路径下的test路径下的所有文件压缩到test.jar中,并由e选项指定test.Test类作为程序入口

  2. 解压:jar xf xxx.jar

  3. 更新:jar uf xxx.jar xxx.class

    需要提示信息加上v选项就可以了

  4. 运行可执行jar包:java -jar test.jar或者javaw test.jar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值