Java基础03—面向对象

本文是学习Java时所记录的学习笔记,本节包含了Java面向对象的概念以及各类成员介绍,是从《疯狂Java讲义第四版》中学习,提取了部分我觉得是重点的内容。欢迎留言、私信交流~~

面向对象概念

概念内容
3大特性封装、继承、多态
3种类型类、接口、枚举
4个修饰符private | protected | public、final、static、abstract
5大成员类、成员变量、方法、构造器、初始化块
  • Java源程序的结构:
    • 一条package语句
    • N条import语句
    • N个class定义
名称修饰符
public,final,abstract
成员变量public | protected | private,static,final,transient
方法public | protected | private,static,final | abstract
构造器public,protected,private

定义类(class)

类简介
  • 类有以下作用
    • 定义变量
    • 创建对象
    • 调用类方法或访问类变量、派生子类。
  • 定义类语法
    • 一个类中,最多只有5种成分
    • [修饰符] - 可以省略,可以是public/final/abstract
    • 一个文件可以有很多个类,但是只能有一个public类
    [修饰符] class 类名 extends 父类
    {
        //零个到多个构造器定义...
        //零个到多个成员变量(field)...
        //零个到多个方法...
    }
    

定义成员变量(field)

  • 定义成员语法】
    • [修饰符] - 可以省略。可以是:public|protected|private,static,final。transient。
    • 类型 - 不能省略。可以是基本类型:数组/类/接口/枚举
    [修饰符] 类型 成员变量名 [ = 默认值];
    

定义方法

  • 定义方法语法
    • [修饰符] - 可以省略。可以是:public|protected|private,static,final|abstract
    • [方法返回值类型] - 基本类型。如果没有返回值,则必须用void来声明。
    • [形参声明] - 每个形参都满足“类型 数量”的格式,多个之间用英文逗号隔开。
    • 每一个方法在内存中都会新建一个栈。
    [修饰符] 方法返回值类型 方法名(多个形参声明)
    {
        //由零条到多条可执行性语句组成的方法体。
        //如果方法签名中有返回值类型声明,该方法里必须包含有效的return语句。
    }
    

定义构造器

  • 构造器可认为是一种特殊的方法,但构造器的作用,是用于产生对象的。
  • 定义构造器语法
    • [修饰符] - 可以省略。可以是:public、protected、private
    • 构造器名 - 必须和类名相同。
    • 如果程序员没有提供构造器,那么系统会提供一个无参数的构造器。
    [修饰符] 构造器名(形参列表)
    {
        //由零条到多条可执行性语句组成的构造器执行体
    }
    

对象的产生和使用

  • 对象作用:调用实例方法或访问实例变量。
  • 实例化person类
    • 定义一个Person类型的变量,通过new关键字调用Person类的构造器,返回一个Person实例,并将Person实例赋给p变量
    • p是一个局部变量
    • Person对象存放在堆里,p引用变量保存在main方法栈里(哪个方法定义的局部变量就保存在哪个栈里)。
    Person p = new Person();
    

this关键字

  • this引用

    • This关键字总是指调用该方法的对象。
      • 当this在方法中时,this代表调用该方法的对象。
      • 当this在构造器中时,this代表该构造器正在初始化的对象。
  • this调用

    • 用来调用另一个重载的构造器,让代码更简洁(不用复制粘贴代码)。
  • This调用只能在构造器的第一行出现。

  • JAVA语法规定:静态成员不能访问非静态成员。(如带有static修饰的静态方法,不能直接调用非static修饰的方法)

方法详解

  • 方法具有所属性,从语法的角度来看,方法必须定义在类中。
    • 有 static 修饰的成员,属于类本身。
    • 没有 static 修饰的成员,属于实例。
  • 静态方法里不能出现this和super。
  • 调用方法的时候,必须要有主语(类或者实例)。

方法的参数传递机制

  • 值传递(副本传递)。
    • “int… nums”代表可以传入N个参数值(个数可变)。
  • 每个方法最多只能一个形参个数可变的参数。
  • 形参可变的参数必须放在最后面。
  • 如果定义方法是声明了形参,调用时必须传入对应参数。
  • 方法传递仅是值传递。传入的是参数的副本,不是参数本身。
  • 如果传递的参数是基本类型,方法中对参数所做的修改,不会影响参数本身。
  • 如果传递的参数是引用类型,因此方法修改会影响参数本身所指向的对象。

递归方法

  • 方法调用自身——隐式循环。
    • 要避免无限循环,一定要有可能出现某些情况下,不再调用方法自身。
  • 案例
    • 问题:f(1)=2;f(2)=5;…f(n)=f(n+2)-2*f(n+1)。计算f(10)是多少。
    • 解决方法:
      把f(n)=f(n+2)-2f(n+1)改为f(n)=2f(n-1)+f(n-2)
    public static int fn(int n)
    {
        if (n ==1){
            return 2;
        }else if(n ==2){
            return 2;
        }else{
            return 2*fn(n-1)+fn(n-2)
        }
    }
    

方法重载

  • 同一个类中,有多个同名的方法,但是他们的形参列表不同。就叫方法重载。
  • 口诀:2同1不同。同一个类,同一个方法名,不同形参列表。
  • 修饰符不同不算重载。返回值类型不同也不算重载。

变量详解(成员变量、局部变量)

名称名称1名称2名称3
成员变量(位置:类中定义的是成员变量)类变量(以static修饰)实例变量(不以static修饰)
局部变量(位置:方法中定义的是局部变量)形参普通局部变量代码块的局部变量
  • 成员变量
    • 可以不需要显式初始值,系统可以自动分配初始值。
    • 初始规则与数组元素的初始规则完全相同。
  • 成员变量又分为
    • 类变量(类变量属于类本身,当初始化类时,会为类分配空间,并执行初始化)。
    • 实例变量(实例变量属于对象本身,系统创建对象时,为对象的实例变量分配空间,并执行初始化)。
    • 局部变量:(局部变量必须由程序员赋初始值后才能使用,否则报错)。
  • 判断变量的方法
    • 查看位置
    • 看修饰符

static 关键字

  • 只能修饰类成员
  • static可修饰的成员:成员变量、方法、初始化块、内部类。
  • 有 static 修饰的成员,属于类本身。
  • 没有 static 修饰的成员,属于实例。
  • 例子
    当创建的实例调用带有static的成员变量时,该成员变量并不属于实例。对该成员变量所做的改变,会导致直接在堆内存中更改,其他实例调用时会显示改变后的结果。
    
  • 面试题:static成员和非static成员之间的关系?
    • static成员(4种)不能访问非static成员(5种)。非static成员可以访问static成员。

封装(Encapsulation)

  • 封装包含两方面内容:
    • 隐藏对象的内部实现细节。
    • 公开一些界面。可以通过界面操作对象,不会破坏内部状态。
  • 通过访问控制符实现封装
    • private(类访问权限):该修饰符修饰的成员,只能在该类中被访问。
    • 不写(包访问权限):该修饰符修饰的成员,只能在该类及其类所在包中被访问。
    • protected(子类访问权限):该修饰符修饰的成员,只能在该类、其类所在包和该类的子类中被访问。
    • public(公共):该修饰符修饰的成员可以在任意地方被访问。
  • 指定原则
    • 成员变量,通常用private修饰。
    • 为每个成员变量提供public的getter、setter方法,用于控制该成员变量。
    • 需要暴露的方法,通常用public修饰。
    • 如果希望一个方法主要用于被子类重写,用protected修饰。

包(package)

  • 不同公司可以定义同名的类,可以解决不同公司、不同项目的类名重复的问题。
  • 使用说明
    • 在类名添加一个前缀。
  • 定义包
    1. 在源码顶部中写入“package 包名;”
    2. 将生成的class文件放在对应的文件结构下。
  • 包名命名规则
    • 语法要求,符合标识符规则。
    • 专业要求,推荐用公司域名倒写,再加项目名。
  • 一旦为类指定了包名后,使用该类时应该用完整类名:包名.类名。
  • 导入包
    • import的作用,为了省略写包名。不写则每次需要在类前面加上包名。
    • java程序默认导入了java.lang包下的所有类。
    • 语法
    import 包名.类名; //每次导入一个类
    import 包名.*; //导入包名下的所有类
    
  • 静态导入(import static)
    import:省略写包名。
    import static:可以省略写类名。
    import static 包名.类名.静态成员名; //每次只导入一个静态成员。
    import static 包名.类名.*; //导入指定类的所有静态成员。
    

继承(Inheritance)

  • 一种类与类之间的关系。是一种有一般到特殊的关系,子类是一种特殊的父类。
  • 语法
    [修饰符] class 类名 extends 父类{
    }
    
  • Java的继承,用的是extends单词。
  • 父类(Super class,又叫超类、基类);子类(派生类)
    • Java是单继承,只能有一个直接父类。
    • 如果你不显式继承父类,Java默认是继承Object类(JDK系统提供的类)
  • 继承的作用
    • 子类继承父类,可以得到父类的成员变量和方法。
    • 有的“代码复用”的概念。

方法重写(override)

  • 子类发现父类提供的方法不适合自己时,就要重写父类的方法。
  • 方法重写口诀:2同2小1大。
    • 2同:方法名相同、形参列表相同。
    • 2小:返回值类型相同或更小、声明抛出的异常相同或更小。
    • 1大:访问权限相同或更大。
  • @Override //添加该行内容会告诉系统有方法重写,如果没有方法重写就报错。

super限定

  • super用于限定访问父类定义的实例变量或实例方法。如父类的方法被重写后,可以使用super限定访问父类的方法。
  • 语法
    super.父类定义的实例变量
    super.父类定义的实例方法();
    

子类调用父类的构造器

  • 子类构造器一定调用父类构造器一次。
  • 如果子类构造器没有显式调用父类构造器,系统会自动在子类构造器的第一行调用父类无参数的构造器。
  • 可以在子类构造器的第一行显式使用super调用来调用父类构造器。
  • 如果父类没有无参构造器,则子类构造器必须显式调用(super调用)父类的指定构造器。
  • 语法
    super调用:super紧跟括号。调用父类的构造器。
    		   super(参数);
    

多态(Polymorphism)

  • 如果编译时和运行时类型不一致,就可能出现多态。
  • 术语介绍
    • 变态:同一个类型的实例、在执行同一个方法,个别对象呈现出变异的行为特征。
    • 多态:同一个类型的多个实例、在执行同一个方法,呈现出多种行为特征。
  • Java执行方法时,方法的执行是动态绑定的,方法总是执行变量实际所指对象的方法。
  • 向上转型(upcasting):子类对象可以直接赋值给父类变量。自动转换。
  • 向下转型:父类对象(变量)可以赋值给子类变量。强制转换。
  • Java引用变量的两个类型
    • 编译时类型:声明该变量时指定的类型。在Java程序的编译阶段,Java编译器只认编译时类型。
    • 运行时类型(实际类型):该变量实际所引用的对象类型。

引用变量的强制类型转换

  • 强制类型转换可以借助于类型转换运算符。
  • 语法
    (type)variable
    
  • 强制运算符只能在具有编译类型具有继承关系的变量之间进行强转,否则编译报:不兼容的类型。
  • 如果再编译类型具有继承关系的变量之间转换时,如果被转变量的实际类型,不是要转的目标类型,程序就会引发ClassCastException(类型转换异常)。

instanceof运算符

  • 可以添加instanceof判断被强制的变量是可转换的才进行转换,避免ClassCastException异常。
  • 语法
    变量名 instanceof 类型
    
  • 当变量所引用的对象是后面类的子类的实例,该运算符返回true。
  • instanceof 只有在编译类型具有继承关系之间才能进行判断,否则编译报错:不能兼容的类型。

构造器

  • 用于创建实例时执行初始化。
  • 构造器规则
    • 构造器用于初始化对象。
    • 构造器必须用new来调用构造器。
    • 如果不为类提供构造器,系统会自动为该类提供无参数的构造器。
  • 子类会先执行父类的构造器(最终父类为Object),再执行自身的构造器。

构造器重载

  • 一个类中可以定义多个构造器,形参列表不同。
  • this调用
    //调用同一个类中重载的构造器,只能出现在构造器的第一行。调用同类的其他构造器。
    this(name,color)
    

初始化块

  • 创建对象时对对象进行初始化操作。
  • 语法
    [修饰符] {
    	//初始化块的可执行性代码
    }
    
  • 初始化块没有名字。
  • 初始化块在构造器之前执行。
  • 子类会先执行父类的初始化块(最终父类为Object),再执行自身的初始化块。
  • 修饰符只能出现一个:static
    • 有static叫初始化块(静态初始化块);
    • 无static叫实例初始化块(非静态初始化块)。

实例初始化块

  • 初始化块前面没有static修饰符的叫实例初始化块。
  • 实例初始化块是“假象”,一个类在编译之后,实例初始化块会消失。实例初始化块会被还原到每个构造器的所有代码之前。
  • 实例初始化块的作用,将多个构造器前面部分相同的代码可以提取到实例初始化块中。
  • 只要程序调用构造器创建对象,程序总会先执行实例初始化块。
  • 定义实例变量时指定的初始值,也是“假象”。指定初始值会在编译后变成构造器所有代码之前的一条赋值语句。
  • 定义变量的初始值和初始化块还原到构造器的顺序,按照它们在程序中的顺序来确定先后。

类初始化块

  • 初始化块前面有static修饰符的叫类初始化块。
  • 负责对类执行初始化。
  • 当程序第一次主动使用该类,系统会为类分配内存空间、并执行初始化(调用类初始化块)
  • 只要你使用该类,都算主动使用。除了仅适用类声明变量
  • 定义类变量时指定的初始值,也是“假象”。指定初始值会在编译后变成初始化块中的一条赋值语句。
  • 定义类变量时指定初始值和类初始化块中的语句,先后顺序由它们本身所在程序中的位置来决定。
  • 初始化任何类之前,一定先从Object开始初始化,依次初始化它所有祖先类,最后才到他自己。
  • 创建任何对象时,一定先从Object构造器开始执行,执行它所有祖先的构造器,最后才执行它自己构造器!

包装类

  • Java有8个基本类型:byte、short、int、long、float、double、char、boolean
  • 把基本类型包装成对象,就叫包装类。
    基本类包装类
    byteByte
    shortShort
    intInteger
    longLong
    floatFloat
    doubleDouble
    charCharacter
    booleanBoolean
  • JAVA 1.5之后的更新:
    • 自动装箱:基本类型的值可以自动当成包装类的实例使用。
    • 自动拆箱:包装类的实例可以自动当成基本类型的值使用。
  • 做项目时,通常兼用使用包装类声明变量。
  • 相关方法
    Integer.parseInt()	//可将字符串转成Int类型。
    Long.parseLong()	//可将字符串转成Long类型
    XXX.parseXXX()	//可将字符串转成对应的XXX类型
    
  • 报错NumberFormatException:要转的字符串不符合数值格式
  • 当程序对Integer使用自动装箱时,它有一个缓存机制,它会缓存-128~127之间的对象。

常用的方法重写(toString、equals)

toString()方法
  • 程序打印对象时,或把对象自动转字符串时,实际用的是该对象的toString()方法的返回值。
  • Object提供的toString方法返回:类名@hashcode方法返回值。
  • 重写内容:重写为返回当前对象的内部状态。
  • 例子
    @Override
    public String toString()
    {
        return "chongxie[a="+a+"],[b="+b+"];";
    }
    
equals()方法
  • 判断两个对象是否相等。
  • 重写内容:根据业务规则来添加相等的标准。添加比较关键属性,来判断两个对象是否相等。
  • 例子
    @Override
    public boolean equals(Object obj){
        if(this == obj){
            return true;
        }
        if(obj != null && obj.getClass()==Goat.class){
            Goat target = (Goat)obj;
            return this.color.equals(obj.color)&&this.weight==obj.weight;
        }
        return false;
    }
    
  • x.getClass() == Goat.class 获取x的类型,并且和Goat.class相比较,如果两个类型相等则返回ture。

单例模式

  • 在某些场景下,某些类只需要(只能)创建一个实例。比如系统的窗口管理器。
  • 单例模式的设计方式:
    • 隐藏构造器(private)——避免创建实例。
    • 暴露一个static的方法,该方法用于创建实例。该方法需要保证只能创建一个实例。
  • 例子
    private static Singleton s;
    private Singleton(){}
    public static Singleton create(){
        if(s == null){
            s = new Singleton();
        }
        return s;
    }
    

Final修饰符

  • final修饰变量 - 该变量只能被赋值一次,不可改变。
  • 可修饰的成员:变量(成员变量和局部变量)、方法、类
  • final成员变量】
    • final修饰的成员变量(field),必须由程序员执行初始化。
    • final修饰实例变量可在以下3个地方指定初始值:
      • 定义时制定初始值
      • 初始化块
      • 构造器
    • final修饰的类变量可以在以下2个地方指定初始值
      • 定义时指定初始值
      • 类初始化块
  • final局部变量
  • final修饰的变量,它会被执行“宏替换”(相当于查找、替换)。
  • 如果final修饰的变量,可以在编译时就确定它的值,那么这个变量就不存在!
  • 建议执行“宏替换”的变量,变量名应该多个单词连缀而成,所有字母大写。
  • final方法
    • final修饰的方法不能被重写。优点:防止父类方法被破坏。
    • final与private在一起没有价值。(都不能被重写)
  • final类
    • final类不能有子类。优点:安全。

abstract修饰符

  • 具有抽象的作用,没有具体的内容,需要子类来重写抽象方法。不能创建实例。
  • 可修饰的成员:类或方法。
  • JH:抽象方法只有方法签名,没有实现的内容(没有“{}”块)。
  • JH:抽象类有构造器,但是无法通过抽象类的构造器创建实例。
  • JH:在类中加入abstract修饰符,就变为抽象类。在方法中加上abstract修饰符,去掉“{}”再加上“;”,就变成抽象方法。
  • 抽象类:主要与“模板模式”联系在一起。
    • 抽象类例子
      • 定义了抽象类需要获取车的速度(周长*转速),通过新建小轿车和坦克的子类(他们的周长不同,子类里才能知道他们的车轮周长的计算方法),重写抽象方法,在运行时可以多态显示结果。
    • 需求场景
      • 程序要实现A方法,需要调用B方法。B方法中暂时不知道该如何实现,就需要把B方法定义成抽象方法。
    • 抽象类定义子类
      • 子类要为抽象父类的所有抽象方法提供实现,否则子类也只能是抽象类。
    • 虽然不能创建实例,但是依然有构造器,作用是提供子类的构造器调用。
    • 可以没有抽象方法。
    • 抽象类不能创建实例,即使没有包含抽象方法。
    • 主要用于派生子类
  • 抽象方法
    • 没有方法体。
    • 主要用于重写方法。
    • abstract与final不能同时出现
    • abstract与static不能同时修饰方法
    • abstract与private不能同时修饰方法
  • 例子
  • JH:形状类是抽象类,2个子类分别是三角形和圆形。通过子类实现了计算周长的抽象方法。
    abstract class xingzhuang 
    { 
        private String color; 
        public abstract double getzhouchang(); 
        public abstract String getType(); 
        public xingzhuang(){} 
        public xingzhuang(String color) { 
            this color = color;
        } 
        public void setcolor(String color){ 
            this color = color;
        } 
        public String getcolor(){ 
            return this color;
        } 
    } 
     
    class sanjiaoxing extends xingzhuang{ 
        private double a; 
        private double b; 
        private double c; 
        public sanjiaoxing(String yanse,double i,double j,double k){ 
            super(yanse); 
            if (i>j+k||j>i+k||k>i+j){ 
                System out println("三角形输入的尺寸不成立");     
                return; 
            } 
            this a = i;
            this b = j;
            this c = k;
        } 
        public double getzhouchang(){ 
            return a+b+c; 
        } 
        public String getType(){ 
            return "三角形"; 
        } 
    } 
     
    class yuanxing extends xingzhuang{ 
        private double r; 
        public yuanxing(String yanse,double i){ 
            super(yanse); 
            this r = i;
        } 
        public double getzhouchang(){ 
            return 2*Math PI*r;
        } 
        public String getType(){ 
            return "圆形"; 
        } 
        public static void main(String[] args){ 
            xingzhuang san1 = new sanjiaoxing("黑色",5,5,5); 
            System out println("形状"+san1 getType()+"的颜色为"+san1 getcolor()+"。它的周长为:"+san1 getzhouchang());  
            xingzhuang yuan1 = new yuanxing("红色",5); 
            System out println("形状"+yuan1 getType()+"的颜色为"+yuan1 getcolor()+"。它的周长为:"+yuan1 getzhouchang());  
        } 
    } 
    

接口(Interface)

  • 接口往往是和设计模式结合一起的。主要是在“面向接口编程”时提供更灵活的机制。
  • 概念:可以认为接口是一种“彻底”的抽象类。
  • 语法
    • [修饰符] - public,省略。
    • [接口名] - 多个单词连缀而成,每个单词的首字母大写。推荐接口用“形容词”。C#推荐接口以I开头。
    • [接口里的field] - 默认有3个修饰符:public、static、final。写或不写,默认都有。声明时必须制定初始值。
    • [接口里的方法] - 默认有2个修饰符:public、abstract。写或不写,默认都有。
    • [接口里的内部类、内部接口、内部枚举] - 默认有2个修饰符:public、static。写或不写,默认都有。
    [修饰符] interface 接口名
    {
        //0~N个field定义。
        //0~N个抽象方法。
        //0~N个内部类、内部接口、内部枚举定义
    }
    
  • 接口不能有构造器,不能有初始化块。
  • 一个接口可以有N个直接父接口。
  • 接口可用于定义变量。
  • 接口不能直接创建实例。
  • 接口最大用途就是供其他类来实现自己。
  • 接口实现
    class 类名 implements 接口名 //实现一个或N个接口。
    
  • 一个类实现接口之后,要么实现类要为接口的所有抽象方法提供实现,要么实现类也是抽象类。
  • 例子
    • JH:定义一个Ilearn接口,使用匿名内部类方式创建接口的实例。
    interface Ilearn{
        public final String name = "张三";
        public abstract String zhuanye();
    }
    
    class jisuanji implements Ilearn{
        public String zhuanye(){
            return "计算机";
        }
        public static void main(String[] args){
            System out println(new Ilearn(){
                public String zhuanye(){
                    return "测试";
                }
                public String toString(){
                    return name+zhuanye();
                }
            });
        }
    }
    

内部类

  • 把一个类放在类里面定义就是内部类。又叫“寄生类”。外部类又叫“宿主类”。
  • 修饰符:private|protected|默认|public
  • 内部类生成的class文件名字为:外部类$内部类.class
  • JH:非静态内部类的成员只在非静态内部类中随意使用,如果外部类需要使用其中的成员,则需要创建非静态内部类的对象来调用。
  • 非静态内部类的可以直接访问外部类的private成员。
  • 非静态内部类
    • 内部类可以直接访问外部类的private成员(field、方法和构造器)。访问方法:加上“类名.this.变量名”。
    • 没有static修饰的内部类的实例,必须寄生在“外部类”的实例里。
    • 非静态内部类,也属于非静态成员。
  • 静态内部类
    • 有static修饰的内部类的实例,必须寄生在“外部类”的类本身中。
    • 静态内部类,属于静态成员,不能访问外部类的非静态成员(field、方法)
  • 使用内部类】
    1. 非静态内部类
      • 声明变量方法:
      外部类.内部类 变量名;
      
      • 创建非静态内部类的实例:
      • 必须先创建外部类的实例。然后用“宿主.new 外部类构造器();”
      Outer.Inner in;
      Outer ou = new Outer();
      in = ou.new Inter();
      
      • 简写为一句:
      外部类.内部类 变量名 = new 外部类().new 内部类();
      
      • 非静态内部类的派生子类
      extends 外部类.内部类  //在类的后面加这一段
      
      • 因为Outer.Inner是非静态内部类,所以必须在子类构造器中使用外部类对象去调用非静态内部类的构造器。
      new 外部类().super();
      //new一个宿主对象调用,使用两条中的其中一条即可
      ou.super();
      //使用已有宿主对象调用,使用两条中的其中一条即可
      
    2. 静态内部类
      • 因为静态类寄生在外部类的类本身里,所以一般不需要程序员去理会外部类。
      • 可以把外部类当成静态内部类的包就可以了。

局部内部类

  • 在方法中定义的类称之为局部内部类。
  • 局部内部类只能在当前方法使用。
  • 局内内部类的文件命名规则:外部类$N内部类.class
  • 一个外部类,可以在不同方法中定义多个同名局部内部类。
  • 不能用static、访问控制符修饰。
  • 可以用final修饰。

匿名内部类

  • 没有名字的内部类,程序无法再访问匿名内部类。程序创建匿名内部类时,会立即创建匿名内部类的实例。
  • 匿名内部类实际返回的是匿名内部类的实例,程序以后只能使用匿名内部类的实例。
  • 匿名内部类没有构造器。
  • 匿名内部类语法
    new 接口() | 父类构造器(参数)
    {
    	//类体部分		
    }
    
  • 规则
    1. 匿名内部类必须显式继承一个父类,或实现一个接口。
    2. 匿名内部类必须实现接口或抽象类中所有抽象方法。
    3. 匿名内部类不能有构造器。
  • 例子
    • JH:使用匿名内部类创建接口的实例。
      interface Ilearn{
          public final String name = "张三";
          public abstract String zhuanye();
      }
      class jisuanji implements Ilearn{
          public String zhuanye(){
              return "计算机";
          }
          public static void main(String[] args){
              System out println(new Ilearn(){
                  public String zhuanye(){
                  return "测试";
              }
              public String toString(){
                  return name+zhuanye();
              }
              });
          }
      }
      

枚举(JDK 1.5)

  • 用于代表“实例已经固定”的类,而且定义时必须在第一行创建并列出来。
  • JH:通常枚举类的成员变量都使用private final修饰。Enum类的成员变量值不允许修改会比较合理。
  • 可以在枚举类中定义抽象方法,但需要在所有枚举值中对其进行实现。
  • 语法
    • [修饰符] - 可以上public|省略、abstract|final(总有其中一个)。
    修饰符 enum 枚举名{
        //立即在第一行该枚举的所有实例。
    }
    
  • 默认继承了java.lang.Enum类。
  • 枚举类的构造器只能使用private访问控制符。
  • 所有的枚举都有一个values()方法,该方法返回所有的枚举实例。
  • 实例名要包含构造器的参数。
  • 包含抽象方法的枚举类
    • 使用匿名内部类实现抽象方法。例如新建加减乘除实例,在列出实例时使用匿名内部类。
  • 枚举可以实现接口
    • 实现接口,并直接实现所有的抽象方法,此时枚举不是抽象枚举。
    • 实现接口,但并不直接实现抽象方法,此时枚举是抽象枚举。
  • 相关方法
    Gender g = Enum.valueOf(Gender.class , “FEMALE”)
    //通过Enum的valueOf方法,获得Gender.class的FEMALE枚举值。
    for (xingbie a:x.values()){System.out.println(a); }
    //通过enum的values()方法,可以获取枚举的所有实例。
    

JAR命令

  • 把多个文件打包成一个压缩包,和winzip压缩格式一样。
  • jar压缩的文件默认多一个META-INF的文件夹,该文件夹包含一个Manifest.mf文件(清单)。
  • 压缩包有三种:
    命令说明
    .jar里面包含N个class文件。
    .war(Web)一个Web应用打包生成的包。
    .ear(Enterprise)企业应用打包生成的包。
  • 用法
    命令说明
    c创建新的压缩包
    t列出压缩包里的文件和目录
    x从压缩包中提取指定的(或所有)文佳
    u更新现有的压缩包
    v提供更详细的信息
    f为压缩包指定文件名
    m包含指定清单文件中的清单信息
    e为可执行jar文件的独立应用程序指定应用程序入口点
    -o 仅存储:不压缩,只是打包
    -M | 不创建条目的清单文件META-INF/MANIFEST.NF
  • 例子
    1.创建压缩包
    	jar -cf mytest.jar *.class //压缩*.clss文件,命名为mytest.jar
    	jar -cvf mytest.jar *.clss //压缩*.clss文件,命名为mytest.jar,并显示详情
    2.创建压缩包,不生成清单文件。
    	jar -cMf mytest.jar *.class //压缩*.clss文件,命名为mytest.jar,不生成清单文件
    3.查看压缩包
    	jar -tf mytest.jar //列出mytest.jar的文件和目录
    	jar -tvf mytest.jar //列出mytest.jar详细的文件和目录
    4.解压压缩包
    	jar -xf mytest.jar //解压mytest.jar文件
    	jar -xvf mytest.jar //解压mytest.jar文件,并显示过程
    5.更新压缩包
    	jar -uvf mytest.jar *.clss //更新*.clss文件到mytest.jar压缩包,并显示详情
    6.指定压缩包主类
    	jar -cvfe mytest.jar UserTest *.clss 
    	//把*.class文件压缩为mytest.jar,并显示详情,指定UserTest为该包的主类。
    7.执行jar包
    	java -jar mytest.jar //运行控制台的程序
    	也可在JVM中直接双击执行。
    	javaw -jar mytest.jar //运行有界面的程序
    

JAVA的入口方法

  • 入口方法:
    public static void main(String[] args)   
    
  • public - 因为是外部调用,所以必须用public。
  • static - 无需创建实例,直接用类名调用入口方法。(初次进入不可能有实例)
  • main - 必须为main,告诉系统这是入口。
  • String[] - 默认的长度为0的数组。
    • 使用下面语句添加元素到String[]数组中。
    java 主类类名 第1数组元素 第2数组元素... 
    

获取用户的键盘输入

  • Sytem.in代表键盘——如果直接用System.in很麻烦,通常会进行包装。
    • 传统会包装秤BufferedReader —— 更安全,有完善的异常机制。
    • JDK 1.5增加了一个Scanner —— 更简单。
  • 例子
    import java.util.*;
    Scanner sc = new Scanner(System.in);
    //hasNextLine表示获取下一行。
    while(sc.hasNextLine())
    {System.out.println(sc.hasNextLine());}
    

系统相关的两个类:

System类
  • 代表JVM所在的操作平台。可以获取操作平台相关特性。
    • in - 标准输入。通常标准输入是键盘。
    • out - 标准输出。通常是屏幕。
    exti(int status) //退出虚拟机。
    getenv()  //获取所有环境变量。
    getenv(String name)  //获取指定环境变量的值。
    static Properties getProperties()  //获取所有系统属性。
    static String getProperty(String key)  //获取指定系统属性的值。
    
Runtim类
  • 代表JVM所在的运行时JRE。可以获取JVM相关特性。
    • 典型的单例类,只能通过getRuntime()方法获取实例。
    rt.maxMemory() //查看总内存。
    rt.totalMemory() //查看已用内存。
    rt.freeMemory() //查看空闲内存。
    rt.exec() //运行操作系统已有的命令。
    

处理日期的类

Date
  • 代表一个日期、时间。
    • Deprecated-不推荐。
    new Date(long) //把毫秒数转换为日期,从1970年1月1日开始。
    getTime() //Deprecated,返回一个毫秒。
    
Calendar
  • 代表一个日期、时间。
    • 调用getInstance()获取实例。
    set(年,月,日,时,分,秒) //设置时间。
    set(Field , val) //直接设置某个字段的值。
    getTime() //获取年月时分秒格式的时间。
    add(int field,int amount) //在某个字段原有值的基础上更改,当超过允许范围时发生进位。
    roll(int field,int amount) //在某个字段原有值的基础上更改,当超过允许范围时不进位。
    
System中代表时间的方法
```
System.currentTimeMillis()
//获取从1970年1月1日到现在过了多少毫秒。
```

正则表达式(Regular Expression , RegEx)

  • 可以匹配N个字符换的字符串模板。

  • Java支持的通配符

    通配符说明
    .可以匹配任意字符。
    \s代表一个任意的空白(空格、Tab)。 space
    \S代表一个任意的非空白。
    \d代表一个任意的数字。 digital
    \D代表一个任意的非数字。
    \w代表一个单词字符。 word
    \W代表一个任意的非单词字符。
  • 特殊字符

    特殊字符说明
    ( )例如(com
    [ ]
    { }
    \
    ?
    *
    +
    ^表示一行的开头
    $表示一行的结尾
    |
  • 方括号表达式

    名词方括号表达式说明
    枚举[ax中]代表a或x或中其中的任意一个字符。
    范围[a-f]代表a到f其中的任意一个字符。
    枚举与范围共存[a-f5-7]代表a-f和5-7其中的任意一个字符。
    表示求否[^a-f]不是a-f字符的任意一个字符即可。
    表示求交[a-g&&[^b-d]]在a-g且不是b-d字符的任意一个字符即可。
  • 表示出现次数的“副词”

    符号说明
    ?表示它前面的东西可出现0~1次。
    *表示它前面的东西可出现0~N次。
    +表示它前面的东西可出现1~N次。
    {n,m}表示它前面的东西可出现n~m次。
    {,m}表示它前面的东西最多可出现m次。
    {n,}表示它前面的东西最少可出现n次。
    {n}表示它前面的东西必须出现n次。
  • String里与正则表达式相关的方法

    方法说明
    atches(String regex)判断字符串是否能匹配【正则表达式模板】。
    eplaceALL(String regex, String replacement)把符合正则表达式的替换为新String。
    eplaceFirst(String )
    plit(String regex)
    \w+".matches(str2)//检查str2和前面的正则表达式是否匹配,不匹配返回false。
  • JAVA专门的正则表达式类

    • 如果需要使用复杂的正则表达式,则需要用如下类。
    • import java.util.regex.*;
    • Pattern类 - 代表正则表达式模板。
      • compile()方法 - 实例化一个partern类。
    • matcher类 - 代表一个匹配工具类。
      • find() - 查找下一个匹配正则表达式的字串。
      • group() - 取出上一次与正则表达式匹配的字串。

国际化

  • 希望一个程序,可以“自适应”所有用户环境。英文简写:I18N。本质是“查找、替换”。
  • 国际化步骤
  1. 提供资源文件。
    资源文件  -  负责为程序提供国际化消息
    文件名:<baseName>_语言代码_国家代码.properties
    内容:hello =Hello World!
    内容:hi = {0},hello!i am {1}。  
    //{0}代表第一个占位符,{1}代表第二个占位符。
    处理文件:native2ascii 要处理的文件名 生成的新文件名
    //在老版本中,如果资源文件包含了非西欧字符,需要使用native2ascii来处理这个文件。
    
  2. 使用ResourceBundle类加载国际化资源文件。
    getBundle(baseName, 语言代码_国家代码);
    搜索资源文件的顺序:
        A. baseNaem_语言代码_国家代码.properties
        B. baseName_语言代码.properties
        C. baseName.properties
        如果没有就无效。
    
  3. 调用ResorceBundle的getString()方法输出国家化消息。
  • 描述国家简写的类

    • import java.util.*;
    • Locale类 - 代表语言、国家环境。
      Locale[] locales = Locale.getAvailableLocales()
      //获取Java语言支持的所有Locale。
      getLanguage() //获取语言代码。
      getCountry()  //获取国家代码。
      getDisplayCountry() //获取国家实际的名字。
      getDefault(Locale.Category category) 
      //获取当前计算机的语言、国家环境。例如返回zh_CN。通常写Locale.Category.FORMAT
      
  • 加载国际化资源的类

    • ResourceBundle类
      ResourceBundle bundle = ResourceBundle.getBundle(String baseName, Locale locale)  //加载国家化资源文件。
      bundle.getString("hi")
      //从bundle加载的文件中查找hi对应的字符串进行替换。
      
  • 负责为消息中的占位符填充参数值

    • import java.text.*;
    • MessageFormat类
      format(String pattern, Object... arguments) //模板
      例子:format(bundle.getString("hi"),args[0]) 
      //用arguments依次替换每个占位符。
      
  • 国际化例子

    import java util *;
    import java text *;
    class HelloWorld{
        public static void language(){
        Locale[] yuyan = Locale getAvailableLocales(); 
        for(Locale a : yuyan){
            System out println(a getDisplayCountry()+"==="+a getLanguage()+"==="+a getCountry());
        }
        }
        public static void main(String[] args){
            String a = "lee";
            Locale locales = Locale getDefault(Locale Category FORMAT);
            ResourceBundle bundle = ResourceBundle getBundle("language2local",locales); 
            System out println(MessageFormat format(bundle getString("nianling"),a));
            //HelloWorld language(); 
        }
    }
    

格式化数字和日期

NumberFormat
  • import java.text.*;
  • 格式化数字,将数值转换成相应字符串。
  1. 如下方法可以获取NumberFormat实例。
    方法说明
    getCurrencyInstance()格式化成货币字符串。
    getIntegerInstance()格式化成整型字符串。
    getPercenInstance()格式化成百分号字符串。
  2. 格式化方法
    方法说明
    format(double number)将数值转换成相应的字符串。
DateFormat
  • import java.text.*;
  • 格式化日期,将日期转换成相应字符串。
  1. 如下方法获得DateFormat实例。
    方法说明
    getDateinstance()得到一个日期格式器,格式化出来的字符串只有日期部分。
    getTimeInstance()得到一个时间格式器,格式化出来的字符串只有时间部分。
    getDateTimeInstance()格式化出来的字符串有日期、时间。
    • 可以指定日期、时间的风格:FULL / LONG / MEDIUM / SHORT
    • 还可以传入Locale,用于指定格式化成哪个国家的字符串。
    • 例子
      import static java.text.DateFormat.*;
      //下面的参数省略了DateFormat类。
      DateFormat a = getDateTimeInstance(SHORT,SHORT)
      //18-11-21 下午5:34
      DateFormat a = getDateTimeInstance(MEDIUM,MEDIUM)
      //2018-11-21 17:34:08
      DateFormat a = getDateTimeInstance(LONG,LONG)
      //2018年11月21日 下午05时34分08秒
      getDateTimeInstance(FULL,FULL)
      //2018年11月21日 星期三 下午05时34分08秒 CST
      getDateTimeInstance(SHORT,SHORT,Locale.US) 
      //11/21/18 5:34PM。以美国的显式风格展示。
      
  2. 格式化方法
    a.format(Date d)  //将日期转换成相应字符串。
    
SimpleDateFormat
  • 简单的日期格式器。
    1. 将日期格式化成字符串。
    2. 将字符串解析成日期。
  • 构造器
    • SimpleDateFormat(“yyyy年MM月dd日,是今年的DD日”);
    1. 创建SimpleDateFormat实例,需要传入一个模板字符串。
    2. 如果要把日期格式转换成自定义日期格式,用format方法。
    3. 如果要解析字符串为自定日期格式,用parse方法。
  • 例子
    SimpleDateFormat sdf = new SimpleDateFormat("我的生日:yyyy年MM月dd日");
    Date d = new Date();
    System.out.println(sdf.format(d));
    String dateStr = "2018/11%08 13.12";
    SimleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM%dd HH.mm");
    Date d = sdf2.parse(dateStr);
    Sytem.out.println(d);
    

相关知识

参考资料
  • 《疯狂Java讲义(第4版)》 李刚
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值