JAVA基础笔记

246 阅读11分钟

变量分类

  • 成员变量
  1. 成员变量又称为实例变量,声明在类中,在方法、构造方法、语句块外;
  2. 成员变量从属于对象,随对象创建而创建,在对象销毁时销毁;
  3. 成员变量会默认初始化;
  4. 成员变量对于类中的方法、构造方法、语句块是可见的;
  5. 访问修饰符可以修饰成员变量
  6. 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。

局部变量

  1. 局部变量声明在方法、构造方法、语句块中;
  2. 局部变量在方法或者语句块执行时被创建,当方法执行完成时销毁;
  3. 访问修饰符不能作用于局部变量;
  4. 局部变量作用范围在声明它的方法或者去语句块中;
  5. 局部变量在栈上分配;
  6. 局部变量没有初始值,必须初始化后才能使用,否则编译报错;
  • 静态变量
  1. 静态变量又称为类变量,在类中以关键字static修饰,但不能在方法中;
  2. 静态变量从属于类,每个类只有静态变量的一份拷贝;
  3. 静态变量除了被声明为常量外很少使用。常量是指声明为public/private,final和static类型的变量。常量初始化后不可改变。
  4. 静态变量储存在静态存储区。经常被声明为常量,很少单独使用static声明变量。
  5. 态变量在第一次被访问时创建,在程序结束时销毁。
  6. 与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为public类型。
  7. 默认值和实例变量相似。数值型变量默认值是0,布尔型默认值是false,引用类型默认值是null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
  8. 静态变量可以通过:ClassName.VariableName的方式访问。
  9. 类变量被声明为public static final类型时,类变量名称一般建议使用大写字母。如果静态变量不是public和final类型,其命名方式与实例变量以及局部变量的命名方式一致。

数据类型

1 基本数据类型

  • 数值类型
    1. 整型类型(byte,short,int,long),分别为1,2,4,8字节
    2. 浮点类型(float,double),分别为4,8个字节

    浮点数的默认类型为double类型;
    科学计数法表示,例如: double a = 314e-2;// 314 * 10^-2
    使用float类型要在数值后面加F,例如3.14F;
    浮点型数值都不能精确表示

  • 字符型 char
    char占两个字节
    System.out.println('a' + 'b');

 输出结果为:

    195

 因为char遇到“+”自动转换成数值

   System.out.println("" + 'a' + 'b');

 输出为:

  ab
  • 布尔型 boolean

2 引用类型

  • 接口
  • 数组

java面向对象

继承

继承的特点:

  1. 子类拥有父类非 private的方法和属性
  2. 子类可以对父类进行扩展,拥有自己的属性和方法
  3. 子类可以用自己的方式实现父类的方法(子类可以改写父类的方法)
  4. Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  5. 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差

继承的类型:

继承的关键字

继承可以用extends(继承类)和implements(继承接口)这两个关键字实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

  • extends关键字

  Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

  • implements关键字

  使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
例子:

public interface A {
    public void eat();
    public void sleep();
}
 
public interface B {
    public void show();
}
 
public class C implements A,B {
}
  • surper和this关键字
  1. super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
  2. this关键字:指向自己的引用。
  • final关键字
    final 关键字声'明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写
  1. 修饰类当用final去修饰一个类的时候,表示这个类不能被继承。注意:a.被final修饰的类,final类中的成员变量可以根据自己的实际需要设计为fianl。b.final类中的成员方法都会被隐式的指定为final方法。说明:在自己设计一个类的时候,要想好这个类将来是否会被继承,如果可以被继承,则该类不能使用fianl修饰,在这里呢,一般来说工具类我们往往都会设计成为一个fianl类。在JDK中,被设计为final类的有String、System等。
    代码:

  2. 修饰方法 被final修饰的方法不能被重写。 注意: a. 一个类的private方法会隐式的被指定为final方法。 b. 如果父类中有final修饰的方法,那么子类不能去重写。
    代码:

  3. 修饰成员变量 注意: a. 必须要赋初始值,而且是只能初始化一次。
    代码:

  4. 修饰成员变量

注意: a. 必须初始化值。 b. 被fianl修饰的成员变量赋值,有两种方式:1、直接赋值 2、全部在构造方法中赋初值。 c. 如果修饰的成员变量是基本类型,则表示这个变量的值不能改变。 d. 如果修饰的成员变量是一个引用类型,则是说这个引用的地址的值不能修改,但是这个引用所指向的对象里面的内容还是可以改变的。
代码:

重写(Override)与重载(Overload)

重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。

class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}
 
class Dog extends Animal{
   public void move(){
      System.out.println("狗可以跑和走");
   }
}
 
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal(); // Animal 对象
      Animal b = new Dog(); // Dog 对象
 
      a.move();// 执行 Animal 类的方法
 
      b.move();//执行 Dog 类的方法
   }
}

运行结果:

动物可以移动
狗可以跑和走

在上面的例子中可以看到,尽管 b 属于 Animal 类型,但是它运行的是 Dog 类的 move方法。 这是由于在编译阶段,只是检查参数的引用类型。 然而在运行时,Java 虚拟机(JVM)指定对象的类型并且运行该对象的方法。 因此在上面的例子中,之所以能编译成功,是因为 Animal 类中存在 move 方法,然而运行时,运行的是特定对象的方法。
例子2:

class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}
 
class Dog extends Animal{
   public void move(){
      System.out.println("狗可以跑和走");
   }
   public void bark(){
      System.out.println("狗可以吠叫");
   }
}
 
public class TestDog{
   public static void main(String args[]){
      Animal a = new Animal(); // Animal 对象
      Animal b = new Dog(); // Dog 对象
 
      a.move();// 执行 Animal 类的方法
      b.move();//执行 Dog 类的方法
      b.bark();
   }
}


以上编译运行结果:

TestDog.java:30: cannot find symbol
symbol  : method bark()
location: class Animal
                b.bark();
                 ^

该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。

方法重写的规则

  1. 方法名和、、、、、参数列表必须与被重写方法完全一样
  2. 返回类型可以和被重写方法(父类方法)返回不一样,但是必须是父类的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
  3. 访问权限不能比被重写方法的访问权限更低,例如一个父类的方法声明为public,那么它的子类重写该方法时只能是public,而不能是protected或者更低
  4. 父类的成员方法只能被它的子类所重写
  5. 声明为final的方法不能够被重写
  6. 声明为static的方法不能够被重写,但是可以被再次声明,如果子类中也含有一个返回类型、方法名、参数列表均与之相同的静态方法,那么该子类实际上只是将父类中的该同名方法进行了隐藏,而非重写,类引用指向子类对象时,只会调用父类的静态方法。所以,它们的行为也并不具有多态性。
  7. 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
  8. 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
  9. 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  10. 构造方法不能被重写。(构造方法和类名相同,显然不符合重写的该概念:)
  11. 如果不能继承一个方法,则不能重写这个方法。

重载

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。 每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。 最常用的地方就是构造器的重载。

重载的规则

  1. 被重载的方法必须改变参数列表(参数个数或类型不一样或参数顺序类型不一样);
  2. 被重载的方法可以改变返回类型;
  3. 被重载的方法可以改变访问修饰符;
  4. 被重载的方法可以声明新的或更广的检查异常;
  5. 方法能够在同一个类中或者在一个子类中被重载。
  6. 无法以返回值类型作为重载函数的区分标准(都是以参数列表做区分)

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  1. 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  2. 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  3. 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

多态

多态是同一个行为具有多个不同表现形式或形态的能力。

多态的优点:

  1. 消除类型之间的耦合关系
  2. 可替换性
  3. 可扩充性
  4. 接口性
  5. 灵活性
  6. 简化性

多态存在的三个必要条件

  1. 继承
  2. 重写
  3. 父类引用指向子类对象 例如Person是Child的父类时:
Person c = new Child();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。 使用多态的例子:

public class Test {
    public static void main(String[] args) {
      show(new Cat());  // 以 Cat 对象调用 show 方法
      show(new Dog());  // 以 Dog 对象调用 show 方法
                
      Animal a = new Cat();  // 向上转型  
      a.eat();               // 调用的是 Cat 的 eat
      Cat c = (Cat)a;        // 向下转型  
      c.work();        // 调用的是 Cat 的 work
  }  
            
    public static void show(Animal a)  {
      a.eat();  
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情 
            Cat c = (Cat)a;  
            c.work();  
        } else if (a instanceof Dog) { // 狗做的事情 
            Dog c = (Dog)a;  
            c.work();  
        }  
    }  
}
 
abstract class Animal {  
    abstract void eat();  
}  
  
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void work() {  
        System.out.println("抓老鼠");  
    }  
}  
  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void work() {  
        System.out.println("看家");  
    }  
}

输出:

吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠

多态的实现方式

  • 方式一:重写
  • 方式二:接口
  • 方式三:抽象类和抽象方法

容器