JAVA基础知识语法篇

java知识特性

   这里是对java的一些科普,它的一些特性。
  1. 首先是java的由来,它是由高斯林所创建的,在进击c语言市场时所进行改造的,前身是Oak(得名于java创始人办公室外的一颗橡树)。于1995年5月以java的名称正式发布,并且提出了" Write once,Run anywhere !"的口号。一次编译,随处运行!
  2. 然后就是java语言的语言特性,在后面的介绍会对这几个特性更加的了解。
    (1)简单性:Java语法是C++语法的一个“纯净版本”,相当于对C++做了一个减法。这里没有头文件、指针运算(甚至指针语法)、结构、联合、操作符重载、虚基类等等。不仅如此,Java开发环境远远超出大多数其他编程语言的开发环境。
    (2)面向对象:在java的世界里,一切皆对象。主要特点是编程思想仅仅围绕着对象,对对象的各种操作,各种处理,在后面的多态会认识到java语言的这个特性。
    (3)分布式(微服务):Java有丰富的例程库,用于处理像HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开和访问网络
    上的对象,其便捷程度就好像访问本地文件一样。
    (4)健壮性:Java编译器能够检测许多在其他语言中仅在运行时才能够检测出来的问题。
    (5)安全性:Java适用于网络/分布式环境。为了达到这个目标,在安全性方面投入了大量的精力。使用Java可以构建防病毒、防篡改的系统。
    (6)体系结构中立:Java编译器通过生成与特定计算机体系结构无关的字节码指令来实现这一特性。这就是为什么可以:“Wrice once,Run anywhere”。
    (7)可移植性:Java规范中没有“依赖具体实现的地方”。基本数据类型的大小以及有关运算都做了明确的说明。
    (8)解释性:Java为了实现与平台无关,自己维护了一套基于栈架构的指令集,Java源代码经过编译之后,字节码文件中的指令就是按照自己的指令集来组织的,但是在具体硬件环境中运行时,系统并不能识别,因为Java程序在执行时,Java解释器会逐条的将字节码文件中的指令翻译成CPU的指令集。
    (9)高性能:边解释边执行。
    (10)多线程:它是第一个支持并发程序设计的主流语言。多线程可以带来更好的交互响应和实时行为。
    (11)动态性:它能够适应不断发展的环境。库中可以自由的添加新方法和实例变量,而对客户端没有任何影响。
  3. 然后是java的运行,在cmd中找到指定文件路径,javac -文件 为编译,然后点进去看刚刚的文件夹,发现产生了一个.class文件,然后再java 文件 为执行,然后cmd上就运行出了刚刚的代码,咱第一个代码为输出" Hello Word !",代码如下:
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello,world");
}
}
  1. 如何运行的呢,.class文件最后会在jvm里面进行执行,下面介绍JDK,JRE,JVM的关系:
    *JDK(Java Development Kit):Java开发工具包,提供给Java程序员使用,包含了JRE,同时还包含了编译
    器javac与自带的调试工具Jconsole、jstack等。
    *JRE(Java Runtime Environment):Java运行时环境,包含了JVM,Java基础类库。是使用Java语言编写程序运行的所需环境。
    *JVM:Java虚拟机,运行Java代码
  2. 然后就是关于标识符需要注意的是
    标识符中可以包含:字母、数字以及 下划线和 $ 符号等等。
    注意:标识符不能以数字开头,也不能是关键字,且严格区分大小写。

数据类型与变量

  1. 首先是常量,何为常量,就是固定不变的量,在它被使用前,它是一个确定的且不会自己再改变的量。

  2. 然后是数据类型,在java中数据类型分为两类,一类是基本数据类型,一类是引用数据类型。
    (1)基本数据类型有四类八种
    **四类:整型,浮点型,字符型,布尔型
    **八种:
    byte ——字节型——1一个字节
    short ——短整型——2个字节
    int ——整型——4个字节
    lang——长整型——8个字节
    float——单精度浮点数——4个字节
    double——双精度浮点数——8个字节
    char——字符型——2个字节
    boolean——布尔型——没有明确的规定说明
    以下有几点需要注意的:
    *不论是在16位系统还是32位系统,int都占用4个字节,long都占8个字节
    *整形和浮点型都是带有符号的
    *整型默认为int型,浮点型默认为double
    *字符串属于引用类型。

  3. 然后是变量,变量就是我们定义的一些列拿来做运算,做操作的标识符。定义变量的语法结构为:
    数据类型 变量名 = 初始值;
    需要注意的是字符类型的定义变量方法,为单引号加上所要用到的字符。还有就是布尔类型,它只有true和false两种状态,默认情况下为false。然后就是float类型,因为在java中默认的小数类型为double,所以定义float的时候在数字后面加上f。

  4. 然后是类型转换的,特点:数据范围大的到数据范围小的。需要注意的是:
    注意事项:
    **不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型
    **如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失
    ** 将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查
    **强制类型转换不一定能成功,不相干的类型不能互相转换

  5. 然后是类型提升,不同类型的数据之间相互运算时,数据类型小的会被提升到数据类型大的。需要值得注意的是byte,低于 4 个字节的类型, 会先提升成 int, 再参与计算。

  6. 最后讲的是String类型,字符串类型,它属于引用数据类型,定义方法同上,需要主要的是赋值时需要用" "引用起来.
    然后关于它有一些列的转换,整形转字符串,浮点数转字符串,字符串分别转它们。

  7. int 转成 String

int num = 10;
// 方法1
String str1 = num + ""; 
// 方法2
String str2 = String.valueOf(num);
  1. String 转成 int
String str = "100";
int num = Integer.parseInt(str);

运算符

  1. 除了加减乘除,首先第一个说的是取模,% 跟除号一样,右操作数不能为零。

  2. 然后是增量运算符,算是对加减乘除的一个简写:
    a+=2 相当于a=a+2;
    a-=2 相当于a= a-2;
    a/=2 相当于a=a/2;
    a*=2 相当于a=a*2;

  3. 然后是关系运算符,主要6个关系运算符,计算结果均为true或者false。
    == != >= <= < >
    需要注意的是 ==在java中表示相等,=表示赋值,不要混淆。

  4. 然后是逻辑运算符,&& || !
    &&表示与
    ||表示或
    !表示非
    这里需要注意的是上面的&&和||遵循短路机制,例如&&左边的为false,那么java虚拟机就不会执行右边的,因为整体已经为false。若||左边的为true,那么也不会再去执行右边的。
    然后就是&和|,若两边的表达式为Boolean的时候·也可以作为逻辑运算符,与上面不同的是,这两个符号无短路机制。

  5. 接下来是位运算符,位运算符主要有四个& | ^ ~。
    &是按位与,对于二进制,1 和1 为1,其余为0.
    | 是按位或,也是对于二进制对应的地方进行或运算。
    ~是按位取反,就是1变0,0变1,为一元运算符。
    ^是按位异或,异为1,相同则为0。这里需要注意的是0异或任何数都是任何数。

  6. 然后是移位运算,移位运算符有三个>> << >>>。
    <<为左移,右边补0,这里需要注意的是左移会移掉符号位,可能正数变成负数。
    ,>>为右移,左边正数补0,负数补1
    ,>>>为无符号右移,左边直接补0.
    注意:上面的运算结果均用16进制表示。

  7. 最后是条件运算符,只有一个条件运算符,
    a>b?a:b 看成三部分
    表达式1 ? 表达式2 : 表达式3
    当 表达式1 的值为 true 时, 整个表达式的值为 表达式2 的值;
    当 表达式1 的值为 false 时, 整个表达式的值为 表达式3 的值
    这也是java中唯一的一个三目运算符。

逻辑语句

下面罗列以下各种语句的格式:

  1. if语句:三种形式,可以自己加减。
    if(布尔表达式){
    // 语句
    }
    if(布尔表达式){
    // 语句1
    }else{
    // 语句2
    }
    if(布尔表达式1){
    // 语句1
    }else if(布尔表达式2){
    // 语句2
    }else{
    // 语句3
    }
  2. switch语句
    switch(表达式){
    case 常量值1:{
    语句1;
    [break;]
    }
    case 常量值2:{
    语句2;
    [break;]
    }
    default:{
    内容都不满足时执行语句;
    [break;]
    }
    }
  3. 循环语句
    主要就是for循环和while循环。
    while(循环条件){
    循环语句;
    }
    for(表达式①;布尔表达式②;表达式③){
    表达式④;
    }
  4. break,break用于循环当中,可以中止整个循环。
  5. continue,用于循环当中,中止该次循环,进行下一次循环。

方法的使用

首先说说为什么要用方法。假若你在写一个程序,它需要多次进行一个同样的操作,可能只用十几行写完的代码你可能写了上百行,可以将你觉得它重复的地方很多写成一个方法,下次拿过来直接使用就好,这就是为什么要用方法。
6. 首先是方法的定义
// 方法定义
修饰符 返回值类型 方法名称([参数类型 形参 …]){
方法体代码;
[return 返回值];
}
具体事物具体操作。
7. 然后是方法的调用。
方法名称([参数类型 形参 …]);
调用该方法后,执行完成又会回到调用它的地方。

  1. 实参和形参的的关系。
    在传输数据的时候,传的值是实参,接收的为形参。
    在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体
    例如:
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
swap(a, b);
System.out.println("main: a = " + a + " b = " + b);
}
public static void swap(int x, int y) {
int tmp = x;
x = y;
y = tmp;
System.out.println("swap: x = " + x + " y = " + y);
}
}
// 运行结果
swap: x = 20 y = 10
main: a = 10 b = 20

这里是没有将a和b的值改变的,在swap方法调用时,只是将实参a和b中的值拷贝了一份传递给了形参x和y。
注意:对于基础类型来说, 形参相当于实参的拷贝. 即传值调用。
【解决办法】: 传引用类型参数 (例如数组来解决这个问题)
9. 然后就是方法重载,在后面涉及到很大的项目的时候,你所执行的功能很多,而且有很多相似,虽然字母能组成的方法名也很多,但是记不住那么多。所以就用到了方法重载。
特点:方法名称必须相同,传值类型必须不同,返回值可以相同也可以不相同。
这里还有方法签名这个概念,就是解释为什么在同一作用域中为什么能出现多个相同的方法名称。这里使用到的是方法签名。
方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。

  1. 下一个就是递归,就是相当于方法自己调自己,用于把一个问题分细之后,发现每一小步做的都是一样的,这里就能用到递归。
    展示个递归的例子:
    ,N的阶层,每次都是乘比自己小1的数。
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
public static int factor(int n) {
if (n == 1) {
return 1;
}
return n * factor(n - 1); // factor 调用函数自身
}

数组的定义及使用

  1. 什么是数组
    数组:存放相同类型元素的一个集合。
    特点:1,物理地址和逻辑都是相邻的。2,每个空间都有自己的编号(下标),从0开始。3,数组中元素类型相同。

  2. 数组的定义
    类型【】 数组名 = new 类型【长度】。
    int[] array1 = new int[10]; // 创建一个可以容纳10个int类型元素的数组
    double[] array2 = new double[5]; // 创建一个可以容纳5个double类型元素的数组
    String[] array3 = new double[3]; // 创建一个可以容纳3个字符串元素的数组

  3. 数组的初始化
    1,动态初始化
    int[] array = new int[10];
    2,静态初始化
    int[] array1 = new int[]{0,1,2,3,4,5,6,7,8,9};
    静态初始化没有规定数组的长度,但是系统会根据{}里面元素的个数默认长度。
    注:如果定义数组没有进行初始化,那么也会有默认值。
    在这里插入图片描述

  4. 数组中元素的访问
    可以通过下标访问数组中任何位置的元素。
    array[0];
    array[1];
    也可以通过其进行赋值。
    遍历数组1,:
    int[]array = new int[]{10, 20, 30, 40, 50};
    System.out.println(array[0]);
    System.out.println(array[1]);
    System.out.println(array[2]);
    System.out.println(array[3]);
    System.out.println(array[4]);
    遍历数组2,:
    int[]array = new int[]{10, 20, 30, 40, 50};
    for(int i = 0; i < 5; i++){
    System.out.println(array[i]);
    }
    遍历数组3,:
    通过for each进行遍历
    int[] array = {1, 2, 3};
    for (int x : array) {
    System.out.println(x);
    }

  5. 数组转字符串
    将数组中的元素转换为字符串
    import java.util.Arrays
    int[] arr = {1,2,3,4,5,6};
    String newArr = Arrays.toString(arr);
    System.out.println(newArr);
    // 执行结果
    [1, 2, 3, 4, 5, 6]

  6. 查找数组中的元素
    1,顺序查找

public static void main(String[] args) {
int[] arr = {1,2,3,10,5,6};
System.out.println(find(arr, 10));
}
public static int find(int[] arr, int data) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == data) {
return i;
}
}
return -1; // 表示没有找到
}
// 执行结果
3

2,二分查找(前提是数组原本有序)
二分查找的思路是先取中间位置的元素, 然后使用待查找元素与数组中间元素进行比较:

int mid = (left + right) / 2;
if (toFind < arr[mid]) {
// 去左侧区间找
right = mid - 1;
} else if (toFind > arr[mid]) {
// 去右侧区间找
left = mid + 1;
} else {
// 相等, 说明找到了
return mid;
}
}
// 循环结束, 说明没找到
return -1;
}
// 执行结果
5
  1. 数组排序
    冒泡排序:
    将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素就在数组的末尾, 依次从上上述过程,直到数组中所有的元素都排列好
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 1; j < arr.length-i; j++) {
if (arr[j-1] > arr[j]) {
int tmp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = tmp;
}
}
} // end for
} // end bubbleSort
// 执行结果
[2, 5, 7, 9]
  1. 二维数组
    二维数组本质上还是一维数组,只不过每个元素又是一个一维数组。
    int[][] arr = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
    };

类和对象

  1. 类的定义和使用
    类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
    类的定义:
    // 创建类
    class ClassName{
    field; // 字段(属性) 或者 成员变量
    method; // 行为 或者 成员方法
    }

  2. 类的实例化
    类的实例化通俗来说就new一个对象,创建对象的过程就是类的实例化。
    PetDog dogh = new PetDog(); //通过new实例化对象

  3. 类和对象的说明
    1, 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员.,
    2,类是一种自定义的类型,可以用来定义变量.
    3,一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量,
    4, 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间

  4. this的引用
    为什么要有this的引用?
    形参名不小心和成员变量名相同:
    public void setDay(int year, int month, int day){
    year = year;
    month = month;
    day = day;
    }
    什么是this引用?
    this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
    public void setDay(int year, int month, int day){
    this.year = year;
    this.month = month;
    this.day = day;
    }
    这样就可以解决了
    注意:this引用的是调用成员方法的对象。

  5. this引用的特性
    1, this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
    2,this只能在"成员方法"中使用
    3,在"成员方法"中,this只能引用当前对象,不能再引用其他对象

  6. 初始化对象
    通过new一个对象之后,用 . 即可调用该对象的成员变量或者成员方法

  7. 构造方法
    构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
    在自己写了构造方法之后,构造对象的时候系统自动执行你所写的构造方法,若你的构造方法有相关参数,那么你构造对象时也需要传相关的参数进行构造该对象。
    构造方法的特性:
    1, 名字必须与类名相同
    2,没有返回值类型,设置为void也不行
    3, 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
    4.,构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
    在构造方法中,可以通过this来简化代码
    public Date(){
    this(1900, 1, 1);//必须是构造方法中的第一句
    }

  8. 封装
    封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
    在这里插入图片描述

  9. static成员
    用static修饰的成员变量或者成员方法为静态的,它们是不依靠对象的,就是说在一个类中,你用static修饰的成员变量或者方法可以直接使用,不需要依靠对象的调用。
    静态成员的特性:
    1, 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
    2.,既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
    3.,类变量存储在方法区当中
    4.,生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
    被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。

继承和多态

  1. 继承
    为什么要用继承?
    java是一门面向对象的语言,在代码设计过程中,两个对象存在直接关联的,使用继承就可以达到代码复用性。例如猫和狗,在定义这两个类的时候,它们都有两只眼睛,四条腿,只是它们的行为不同,这里就可以将它们所关联的部分定义一个动物类,然后分别继承这个动物类,这就是继承。
    继承机制:
    是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性
    的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。
    继承主要解决的问题是:共性的抽取,实现代码复用。
  2. 继承的语法
    修饰符 class 子类 extends 父类 {
    // …
    }
    被继承的称为父类,子类继承父类,可以访问父类中相关权限的成员变量或者成员方法。
  3. 父类成员的访问
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}

在子类方法或通过子类对象访问成员时:
1,如果访问的成员变量子类中有,优先访问自己的成员变量。
2,如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3,如果访问的成员变量与父类中成员变量同名,则优先访问自己的
13. super关键字
由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父
类的成员。
在子类方法中,如果想要明确访问父类中成员时,借助super关键字即可。
使用方法:super. 进行调用
注意:super关键字只能在非静态方法中使用。
14. 子类构造方法
父子父子,先有父再有子,子类完成构造方法时必须先帮助父类完成构造方法。再new一个子类对象的时候,也会先调用父类的构造方法,然后再调用子类的构造方法。

public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
// super(); // 注意子类构造方法中默认会调用基类的无参构造方法:super(),
// 用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
// 并且只能出现一次
System.out.println("Derived()");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}
结果打印:
Base()
Derived()

注意:
1, 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
造方法
2,如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3,在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
4,super(…)只能在子类构造方法中出现一次,并且不能和this同时出现
15. super和this
区别
相同点:
1.,都是Java中的关键字
2,只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3,在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点:
1, this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
2, 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
3,在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造
方法中出现
4,构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
16. 代码块的执行顺序
一个类里面有静态代码块,实例代码块,构造代码块。
我们在new一个对象的时候,首先执行的是静态代码块,然后再是实例代码块,最后是构造代码块。
静态代码块只执行一遍,再次new对象的时候,静态代码块并不会再次执行。
若存在继承的关系:
顺序如下:
Person:静态代码块执行
Student:静态代码块执行
Person:实例代码块执行
Person:构造方法执行
Student:实例代码块执行
Student:构造方法执行
person为父类,student为子类。
即先执行父类的静态代码块,然后再子类的静态代码块,然后再是父类的实例代码块和构造代码块,最后是子类的实例代码块和构造代码块。
17. 继承方法
支持一个类继承一个类,父类继承一个类,一个类被多个类继承,但是不支持一个类继承多个类。

我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.
子类如何访问爷爷类?
可以通过父类中写方法对爷爷类进行访问
18. final关键字
final关键字可以修饰变量,成员方法以及类。
1,修饰变量或者字段
表示该变量为常量,不可修改。
2,修饰类
表示此类不能被继承
3,修饰方法
表示该方法不能被重写。
19. 继承与组合
和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

// 轮胎类
class Tire{
// ...
}
// 发动机类
class Engine{
// ...
}
// 车载系统类
class VehicleSystem{
// ...
}
class Car{
private Tire tire; // 可以复用轮胎中的属性和方法
private Engine engine; // 可以复用发动机中的属性和方法
private VehicleSystem vs; // 可以复用车载系统中的属性和方法
// ...
}
  1. 多态
    多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。
    多态即不同形态不同特征,具体用法就是,狗和猫继承了动物类,动物类有一个行为方法,在狗和猫中重写了这个行为方法,然后用动物类去接收狗和猫产生的对象,最后通过这个动物类接收到的对象调用这个行为方法,即可使用猫和狗所对应的行为方法。
  2. 多态实现条件
    1,必须在继承体系下
    2 ,子类必须要对父类中方法进行重写
    3, 通过父类的引用调用重写的方法
    多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。
  3. 重写
    上面所提到的重写:也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
    方法重写规则:
    1,子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
    2,被重写的方法返回值类型可以不同,但是必须是具有父子关系的
    3,访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为 protected,父类被static、private修饰的方法、构造方法都不能被重写。
    4,重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心,将方法名字拼写错了 (比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.
  4. 向上转型
    即用父类来接收子类new的对象
    Animal animal = new Cat(“元宝”,2);
    向上转型的优点:让代码实现更简单灵活。
    向上转型的缺陷:不能调用到子类特有的方法。
  5. 向下转型
    即子类接收父类的对象,但是这样做是有风险的,需要强制转换。
    向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。
    if(animal instanceof Cat){
    cat = (Cat)animal;
    cat.mew();
    }

抽象类和接口

  1. 抽象类的概念
    面对对象中,所有的对象都是用类来描述的,但是不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描述一个对象,那么这个就是抽象类。
    例如形状,圆形可以画圆形,方形可以画方形,很明显都是继承的形状这个类,但是形状这个类不能具体的去画什么,它的画方法无法具体的去实现,所以这里就把形状定为一个抽象类。
    上面说到形状这个类里面画这个方法,它可以通过多态去实现其它子类的画方法,但是它自己并没有实际去做什么,所以这里这个画方法就可以定义为抽象方法,包含抽象方法的类称为抽象类。

  2. 抽象类语法
    在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
    // 抽象类:被abstract修饰的类
    public abstract class Shape {
    // 抽象方法:被abstract修饰的方法,没有方法体
    abstract public void draw();
    abstract void calcArea();
    // 抽象类也是类,也可以增加普通方法和属性
    public double getArea(){
    return area;
    }
    protected double area; // 面积
    }
    注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。

  3. 抽象类的特性
    1,抽象类不能实例化对象。
    2,抽象方法不能是private的。
    3,抽象方法不能是final和static修饰的,因为子类必须重写抽象方法。
    4,抽象类必须被继承,且子类必须重写抽象方法,否则这个子类也必须是抽象类。

  4. 抽象类的作用
    抽象类本身不能实例化,只能通过创建该抽象类的子类,然后让子类去重写该抽象类的抽象方法。
    但是为什么要用抽象类呢?
    使用抽象类的场景就如上面的例子, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.

  5. 接口
    接口的概念:
    接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

  6. 语法规则
    接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。
    public interface 接口名称{}

  7. 接口使用
    接口不能直接使用,必须要有一个实现类来实现这个接口,重写接口中所有的抽象方法。
    用到的关键字为implements
    public class 类名称 implements 接口名称{
    // …
    }
    注意:子类和父类是extends,类与接口是implements的实现关系。

  8. 接口特性
    1,接口也不能实例化对象,是一种引用类型。
    2,接口中每一个方法都是public抽象方法,即接口中的方法会被隐式的认为public abstract
    3,接口中的方法是不能在接口中实现的,只能通过实现接口的类来实现。就是说在接口中里面的成员方法不能带主体,不能有具体的操作。
    4,重写接口的方法时,不能使用默认的访问权限。
    5,接口中可以有变量,但是会被默认为用,public static final 变量。在实现这个接口的类中可以直接通过接口名来进行访问,但是不能对其进行赋值。
    6,接口中不能有静态代码块或者构造方法。
    7,接口虽然不是类,但是在编译器执行后也是.class后缀。
    8,如果一个类没有实现接口的所以方法,那么这个类也必须定义为抽象类。

  9. 实现多个接口
    一个类只能继承一个类,但是一个类可以实现多个接口。
    比如三栖动物,会飞,会游泳,会走路,但是不是所有的动物都会,所以分别实现各自的接口,然后这个动物就实现这三个接口。

  10. 接口间的继承
    在java中,类与类是单继承的,不能实现多继承,一个类可以实现多个接口,接口与接口直接可以多继承,即用接口可以到达多继承的目的。
    接口与接口直接的继承也是用extends。

interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
...
}

此时Frog类实现的接口,就必须继续实现它所实现接口所继承的其他接口内的方法。
11. 抽象类和接口的区别
核心区别:抽象类中可以包含普通方法和普通字段,这样的方法和字段可以被子类直接使用(不必重写),而接口中不能包含普通方法,子类必须重写接口中所有的抽象方法(里面的方法也被默认为抽象方法)。
在这里插入图片描述
12. Object类
在java中,除了Object类,所有类都存在继承关系。默认会继承Object父类。即所有的对象都可以通过Object接收。
如果需要打印对象中的内容,可以重写Object类中的Tostring方法进行打印对象中的类。在使用tostring的时候会首先调用你所写的tostring。
然后需要判断是否相等时用到的equals方法,如果需要对比对象中的内容的时候,必须重写object中的equals方法。

String类

  1. 字符串构造
    public static void main(String[] args) {
    // 使用常量串构造
    String s1 = “hello bit”;
    System.out.println(s1);
    // 直接newString对象
    String s2 = new String(“hello bit”);
    System.out.println(s1);
    // 使用字符数组进行构造
    char[] array = {‘h’,‘e’,‘l’,‘l’,‘o’,‘b’,‘i’,‘t’};
    String s3 = new String(array);
    System.out.println(s1);
    }
    注意:String是引用类型,内部并不存储其本身
    在这里插入图片描述其内部是用一个字符数组进行存储。

  2. String对象的比较
    基本类型的比较用==,在equals方法中,对于基本类型比较其数值,对于引用类型比较的是他们的地址,看是否为同一个对象。但是在String类中重写了equals类。下面是String类中equals的源码:
    public boolean equals(Object anObject) {
    // 1. 先检测this 和 anObject 是否为同一个对象比较,如果是返回true
    if (this == anObject) {
    return true;
    }
    // 2. 检测anObject是否为String类型的对象,如果是继续比较,否则返回false
    if (anObject instanceof String) {
    // 将anObject向下转型为String类型对象
    String anotherString = (String)anObject;
    int n = value.length;
    // 3. this和anObject两个字符串的长度是否相同,是继续比较,否则返回false
    if (n == anotherString.value.length) {
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = 0;
    // 4. 按照字典序,从前往后逐个字符进行比较
    while (n-- != 0) {
    if (v1[i] != v2[i])
    return false;
    i++;
    }
    return true;
    }
    }
    return false;

  3. 字符串查找
    String中提供了以下的方法对字符串进行查找操作:
    char charAt(int index)
    返回index位置上字符,如果index为负数或者越界,抛出
    IndexOutOfBoundsException异常
    int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
    int indexOf(int ch, intfromIndex)
    从fromIndex位置开始找ch第一次出现的位置,没有返回-1
    int indexOf(String str) 返回str第一次出现的位置,没有返回-1
    int indexOf(String str, intfromIndex)
    从fromIndex位置开始找str第一次出现的位置,没有返回-1
    int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1
    int lastIndexOf(int ch, intfromIndex)
    从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返
    回-1
    int lastIndexOf(String str) 从后往前找,返回str第一次出现的位置,没有返回-1
    int lastIndexOf(String str, intfromIndex)
    从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返
    回-1

  4. 大小写转换
    public static void main(String[] args) {
    String s1 = “hello”;
    String s2 = “HELLO”;
    // 小写转大写
    System.out.println(s1.toUpperCase());
    // 大写转小写
    System.out.println(s2.toLowerCase());
    }

  5. 格式化
    public static void main(String[] args) {
    String s = String.format(“%d-%d-%d”, 2019, 9,14);
    System.out.println(s);
    }

  6. 字符串替换
    在这里插入图片描述

  7. 字符串拆分
    按照指定的内容对字符串进行拆分
    String[] split(String regex) 将字符串全部拆分
    String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组
    注意:
    1, 字符"|“,”*“,”+“都得加上转义字符,前面加上 “\” .
    2,而如果是 “” ,那么就得写成 “\\” .
    3,如果一个字符串中有多个分隔符,可以用”|"作为连字符.
    链接: https://editor.csdn.net/md/?articleId=127952497
    具体其他方法看主页或者搜索该链接。

  8. 字符串的不可变性
    在这里插入图片描述
    从上图可以看出,该内部的字符数组是用final修饰的,这样它就不能再指向任何的地址,且它是private,是私有的,再者string类是final修饰,它将不能被继承,所以外界是不能对这个字符数组动手的。
    所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象

  9. 字符串修改
    注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。所以后面引出的stringbuilder和stringbuffer是用来解决这个问题的。

  10. StringBuilder和StringBuffer
    String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder
    注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
    String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
    StringBuilder变为String: 调用toString()方法
    stringbuffer与stringbuilder的区别在于,stringbuffer在使用时上一次锁,对于多线程是安全的,但是正常情况使用的是stringbuilder,毕竟上锁也是需要花费时间的。

认识异常

  1. 异常的概念
    在java中,将程序执行过程中发生的不正常行为称为异常。

  2. 常见的异常:
    1,算术异常
    2,数组越界异常
    3,空指针异常(就是不能去对一个指向null的对象进行操作)
    java中不同类型的异常,都有其对应的类来进行描述。

  3. Error
    erroe是指java虚拟机无法解决的严重问题,一旦发生回力乏术。

  4. 异常的分类
    1,编译时异常
    在程序编译时发生的异常。
    2,运行时异常
    是指在程序执行阶段发生的异常

  5. 解决异常的格式
    try{
    这里需要抛出异常
    }catch(这里是需要捕捉异常的类型){
    这里是捕捉过后执行的操作
    }后面可以跟多个catch
    throw关键字在于抛出异常,必须在方法体内部。

try{
// 将可能出现异常的代码放在这里
}catch(要捕获的异常类型 e){
// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类
时,就会被捕获到
// 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
}[catch(异常类型 e){
// 对异常进行处理
}finally{
// 此处代码一定会被执行到
}

只有当异常被处理后,后面的代码才会被执行,但是无论怎样,finally里面的语句一定会被执行。
28. 自定义异常类
class UserNameException extends Exception {
public UserNameException(String message) {
super(message);
}
}
实现一个带有String类型参数的构造方法,参数含义:出现异常的原因
注意:
自定义异常通常会继承自 Exception 或者 RuntimeException
继承自 Exception 的异常默认是受查异常
继承自 RuntimeException 的异常默认是非受查异常

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShengR_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值