栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

1、 Java基本语法及基础知识

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

1、 Java基本语法及基础知识

抽象类与接口的区别:

  • 相同

    1. 不能实例化
    2. 可以将接口类、抽象类作为引用类型
    3. 一个类如果继承了某抽象类或接口;需要对其中的抽象方法全部实现,否则该类仍为抽象类
  • 不同:

    • 抽象类:

      1. 可以定义构造函数(构造器)
      2. 可以有抽象方法、具体方法、可包含静态方法
      3. 抽象类中成员是private、protected、public、默认
      4. 可定义成员变量
      5. 可以没有抽象方法
      6. 一个类只能继承一个抽象类
    • 接口

      1. 不能定义构造函数(构造器)
      2. 都是抽象方法,不能有静态方法
      3. 接口的成员都是public
      4. 接口定义的成员变量都是常量
      5. 一个类可以实现多个接口
  • 什么时候用接口或抽象类

    • 接口:
      • 接口是事物共有特征的集合
    • 抽象类“
      • 概念: 一类事物:人类,动物;植物
重写与重载
  • 重写:

    • 子类将父类的方法改写
    • 方法名、返回类型、参数须与父类一致
      • 或子类的返回类型是父类返回类型的子类
  • 重载

    • 一个类中,同名方法
      • 不同的参数列表:
        • 参数类型,个数,顺序不同
      • 返回类型没要求;可相同也可不同
== 和equals的区别

八种数据变量中直接存储值

byte 、short、Long、int、float、double 、Boolean、char

八大基本数据类型对应着各自的封装类型,提供了更多的方法,且不进行初始化时值默认为空(基本数据类型必须初始化)

像String类型属于引用类型,变量中存储的是地址,对应的地址存储数据

==:

  • 如果是基本数据类型的变量,则判断两者的值是否相同
  • 引用类型的变量: 判断两者对象的地址是否一致

equals:

  • equals 不能用于基本数据类型
    • equals 继承Object类。比较的是 是否为同一对象
    • 若未对equals 进行重写, 比较的是 引用类型的地址
  • 若重写;则比较对象的内容

如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;

诸如String、Date、File、包装类等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

false,不同对象,其地址不同

true ,值相同

true,基本类型,==判断值

包装数据类型间比较,

equals比较首先比较包装类型是否相同,如果相同,再比较值是否相同,都相同则为true,反之为false

Integer:如果传入的两个值在-128~127之间,那么会把这两个一样的数值放在一个叫常量池的东西里,那么这个时候两个数值比较就是true了

引用类型:

String的equals判断值:String类型之所以equals会比较值内容是因为它重写了

例子:

byte b1 = 127;
Byte b2 = new Byte("127");
Byte b3 = new Byte("127");
System.out.println("Byte 基本类型和包装对象使用 == 比较 : " + (b1 == b2));
System.out.println("Byte 基本类型和包装对象使用 equals 比较 : " + b2.equals(b1));
System.out.println("Byte 包装对象和包装对象使用 == 比较 : " + (b2 == b3));
System.out.println("Byte 包装对象和包装对象使用 equals 比较 : " + b2.equals(b3));


Byte 基本类型和包装对象使用 == 比较 : true  : 拆箱
Byte 基本类型和包装对象使用 equals 比较 : true
Byte 包装对象和包装对象使用 == 比较 : false, 不同对象
Byte 包装对象和包装对象使用 equals 比较 : true

  • 易错:
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1 == i2);//true
System.out.println(i3 == i4);//false   Integer缓存-128到127
        
Double d1 = 100.0;
Double d2 = 100.0;
Double d3 = 200.0;
Double d4 = 200.0;
System.out.println(d1 == d2);//false
System.out.println(d3 == d4);//false  
/  在某个范围内的整型数值的个数是有限的,而(Double、Float)浮点数却不是。

注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。

Double、Float的valueOf方法的实现是类似的。

throw与throws的区别
  • throw是语句抛出异常,出现于函数内部,用来抛出一个具体异常实例,throw被执行后面的语句不起作用,直接转入异常处理阶段,

  • throws:throws是函数方法抛出异常,一般写在方法的头部,用来抛出一些异常,本身不进行解决,抛给方法的调用者进行解决

String、StringBuilder、StringBuffer
  • String 是只读字符串,(final类型的字符串数组)一旦创建就不可更改

    • 每次创建都是新的String对象
  • StringBuilder、StringBuffer 是可对字符串内容修改;且内存地址不变

    • StringBuilder 线程不安全;没有加锁
    • StringBuffer :对其方法加了 synchronized同步锁,线程安全

性能/ 效率: StringBuilder >StringBuffer > String

优先使用StringBuilder ;多线程使用共享变量时使用StringBuffer

声明一个类不会被继承

该类被final修饰,则此类不能有子类,不可被其他类继承

如:Math类

生成对象内存布局:

cat指明一地址,在堆中存储对象cat的数据。

  • 属性:

    • 12是基本数据类型,直接存储
    • String字符串是引用类型;需将其存至常量池,由地址调用
  • Java 内存的结构分析

    • 栈: 一般存放基本数据类型(局部变量)
    • 堆: 存放对象(Cat cat , 数组等)
    • 方法区:常量池(常量,比如字符串), 类加载信息

new(创建对象) 时: Cat c = new Cat();

  • 类加载器,加载cat类的信息(属性、方法);只会加载一次
  • 在堆中分配空间、对cat类进行默认初始化(: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char u0000,boolean false,String null),把堆的地址赋给c
  • 进行指定初始化:如:p.name =”jack” p.age = 10
方法的调用机制原理
  1. 当方法被调用时;会在栈里独立分配一个空间A
  2. 方法结束后;将结果返回至调用方法的地方
  3. 销毁栈空间A。
  4. main栈结束后也销毁。整个程序退出
方法的传参机制 基本数据类型:
public class MethodParameter01 { 

    //编写一个 main 方法 

    public static void main(String[] args) { 
    int a = 10; 
    int b = 20; 
    //创建 AA 对象 名字 obj 
    AA obj = new AA(); 
    obj.swap(a, b); //调用 swap 
    System.out.println("main 方法 a=" + a + " b=" + b);//a=10 b=20 
 }  
} 

class AA { 
    public void swap(int a,int b){ 

    System.out.println("na 和 b 交换前的值na=" + a + "tb=" + b);//a=10 b=20 
    //完成了 a 和 b 的交换 
    int tmp = a; 
    a = b; 
    b = tmp; 
    System.out.println("na 和 b 交换后的值na=" + a + "tb=" + b);//a=20 b=10 
    } 

} 

执行obj.swap(a, b); 时,会另开辟一个栈空间,与main栈相互独立,且期间并无返回值

故没有交换

  • 结论:
    • 基本数据类型传递的是值;形参不会影响到实参
引用类型

引用类型传递的是地址(地址的值);可通过形参影响实参

两个独立栈空间里的arr数组都指向同一个对象

  • 引用类型也是值传递,这里的值是地址的值,也就是指针的值
public class a {

    public static void main(String[] args) {
        Person p = new Person();
        p.name = "jerry";
        p.age = 3;
        B b = new B();
        b.test200(p);
        System.out.println(p.age+"=||"+p.name);
    }
}

class Person {
    String name;
    int age;
    public Person(String name) {
        this.name = name;
    }
}

class B {

    public void test200(Person p) {

//  思考      p.age = 10000; //修改对象属性
//思考
//        p = new Person();
//        p.name = "tom";
//        p.age = 99;
//思考
          p = null;
// 思考
        Person person = new Person("李四");
        p = person; 

    }
}
  1. p.age = 10000; 将传来的p的属性修改;此时用的是同一对象 (引用对象传递地址) 故改变

  2. p = new Person();
    p.name = “tom”;
    p.age = 99; 此时在堆中另创了对象 方法执行结束,这个p就消失了,与main栈无关, 故不变

  3. p = null; 此时将传来的地址设为空,方法执行结束,这个p就消失了。与main栈无关

    ​ 置空相当于把指向的箭头去掉,而不是把数据抹掉。

  4. p = person; 这个和 第二个一样,这个p就消失了

总结:

  • 引用类型参数 只是复制了一份,除了setName() 和 设置属性生效外,其余都不影响实参本身

  • 方法执行完后栈空间copy的那个p引用变量消失(如果没有其他引用指向它,它就会等待垃圾回收器的回收),回到主方法后,首次声明的p引用依然指向原来的p对象。

  • String与 基本数据类型 的类似

    • 因为:String对象一旦创建,内容不可更改。每一次内容的更改都是重现创建出来的新对象。
可变参数
  • 存在多个方法的名、功能、参数属性一致时, 可封装成一个方法:
public int sum(int... nums) { 
    System.out.println("接收的参数个数=" + nums.length);
}
  • int... nums 表示 可输入多个int参数
  • 可变参数本质上是 数组
  • 可变参数与其他参数都放在形参列表时,可变参数必须放在最后
public String getInfo(String name,int... nums) { 
    System.out.println("接收的参数个数=" + nums.length);
}
  • 形参列表只能出现一个可变参数

//细节: 一个形参列表中只能出现一个可变参数

//下面的写法是错的. 

 public void f3(int... nums1, double... nums2) { 

 } 
作用域

变量分为: 成员变量 、 局部变量

  • 成员变量: 也叫全局变量。类的属性,Static修饰成为类变量或静态变量,还有就是方法外的变量。等

    • 作用域:作用于整个类
    • 可以不赋值,直接使用,因为有默认值,
  • 局部变量: 一般是 在成员方法中定义的变量 a 、除属性外的其他变量如:代码块的区域创建的变量

    • 作用域:方法内部 、
    • 必须赋值,没有默认值

    cat类中方法 ha 的变量 a

    public void ha(){
    	int a  = 0;
    }
    

注意事项

  • 成员变量与局部变量可以重名;访问符合就近原则

  • 同一作用域中,变量不能重名

  • 是

  • 成员变量可以被其他类访问;局部变量不行

  • 成员变量可以加 修饰符 ;局部变量不行

  • ​ 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。

  • ​ 局部变量,生命周期较短,伴随着它的代码块的执行而创建,

    伴随着代码块的结束而销毁。即 在一次方法调用过程中 生效

构造器

构造器是初始化对象;并不是创建对象

  • 在创建对象时,会自动调用构造器方法去初始化对象

  • 如果没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)

  • 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器, 除非显式的定义一下,

一个对象的创建
class Person { 
    String name;//默认值 null 
    int age = 11;//默认 0 

//第一个无参构造器:利用构造器设置所有人的 age 属性初始值都为 18 
    public Person() { 
   	 age = 18;// 
    }
    //第二个带 pName 和 pAge 两个参数的构造器 
    public Person(String pName, int pAge) { 
        name = pName; 
        age = pAge; 
  	 } 

}


Person p = new Person("预习",20);

  • 加载类的信息 (只加载一次)
  • 在堆中开辟新的空间;
  • 对象初始化:
    • 且进行默认初始化 (属性的初始值0、null)
    • 进行显式初始化 (null、11)
    • 构造器初始化 (“预习”,20)
  • 将对象在堆中的地址 指向 p
this

java虚拟机会给每个对象分配一个this

this : 表示当前对象。 作用域: 只能在类定义的方法中使用。

  • this可访问 类的 属性、方法、构造器
  • this:用于区分 构造器中的 局部变量和成员变量
public Person(String name, int age) { 
    this.name = name; this.age = age; 
}
// 区分 形参的name 和 类的属性的name
  • this访问构造器
    • this(参数列表); 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器
    • 必须放在第一条语句
    public Person(){
        this("㔿",13);
        sout("123");
    }

    public Person(String name, int age) { 
        this.name = name; this.age = age; 
    }
包
  • 作用:
    • 区分同一名称的类
    • 管理类
    • 控制访问的范围
  • 本质:创建不同的文件夹 / 目录 保存类

java中的包和操作系统没有任何关系,java的包是用来组织文件的一种虚拟文件系统。

不允许包名以java开头,否则会导致命名空间污染的问题

访问修饰符

类的属性、方法符合以下规则

公开: public: 对外公开

受保护: protected: 对子类、同一包下公开

默认: 无修饰符号, 对同一包下公开

私有: private: 对类本身公开

  • 修饰符可 修饰 类、类的属性,成员方法
  • 默认、public 修饰类
public class A { 
//四个属性,分别使用不同的访问修饰符来修饰 
    public int n1 = 100; 
    protected int n2 = 200; 
    int n3 = 300; 
    private int n4 = 400; 
    
    public void m1() { 
    //在同一类中,可以访问 public protected 默认 private 修饰属性和方法 
    System.out.println("n1=" + n1 + " n2=" + n2 + " n3=" + n3 + " n4=" + n4); 
	}
}
package com.hspedu.modifier;
public class Test { 
    public static void main(String[] args) {
        A a = new A ();
        a.m1(); 
    } 
}

为什么Test可以访问n4?

Test测试类是调用对象内的方法,而A对象方法m1是公开的public

调用本类中的四个访问修饰符变量,所以可以访问

面向对象的三大特征

面向对象编程有三大特征:封装、继承和多态

封装

把对象的属性和方法结合成一个独立的整体,隐藏实现细节,并提供对外访问的接口。

继承的细节

继承后,类加载先加载父类的信息

A 继承B后; A就拥有B的属性+方法;所有的子类不需要重新定义这些属性和方法

  • 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

  • 子类必须执行父类的构造器,以初始化父类

  • 子类创建的时候会自动调用父类的无参构造器

    • 如果父类没有无参构造器,则需要子类在构造期中去写父类的其他构造器 super
  • super 仅用于构造器中,必须放在构造器第一行,与this类似

  • 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。

    • 如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】
  • 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

继承的本质:

先看子类

(1) 首先看子类是否有该属性

(2) 如果子类有这个属性,并且可以访问,则返回信息

(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)

(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...
多态

​ 多态是建立在封装和继承基础之上的。

重载、重写就是多态的体现

多态前提: 两个类存在继承关系

向上转型:

​ 父类的引用 指向了子类对象

​ 父类类型引用名 = new 子类类型();

  • 可以调用父类的所有可访问的方法、属性及子类重写的方法
  • javac 编译: 仅能 识别使用父类类型的成员;
    • 不能调用子类的特有的成员
  • 运行时,看子类的的具体实现: 从子类开始(初始化)查找
  • 编译类型看左边;运行类型看右边
向下转型:
  • 条件:
    • 要求父类的引用必须指向的是当前目标类型的对象
    • 就是:目标类型先进行向上转型,
  • 此时可以调用子类所有的成员
Animal animal = new Cat();
Cat cat = (Cat) animal; // 父类的引用

编译类型:cat; 运行类型:cat (强转了)

此时可以调用子类的成员

java 的动态绑定机制
  1. 调用对象方法: 该方法会与该对象的内存地址(运行类型)绑定
    • 也就是 尽管方法名同名,也会调用该对象的方法
  2. 调用对象属性时: 哪里声明,哪里使用
    • 动态绑定只是针对对象的方法,对于属性无效。因为属性不能被重写。

java动态绑定机制 - 捞月亮的渔夫 - 博客园 (cnblogs.com)

Java的动态绑定机制 - eric.dream - 博客园 (cnblogs.com)

原来也有 对象数组

数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用

double scores[] = new double[5];
Person p[]      = new Person[5];
hashCode

返回该对象的哈希值

  • 两个引用指向同一对象;其哈希值一样

  • 两个引用,指向不同对象;哈希值不一样

- 但 两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

以后看到 集合再补

  • 假如只重写equals而不重写hashcode,那么Student类的hashcode方法就是Object默认的hashcode方法,由于默认的hashcode方法是根据对象的内存地址经哈希算法得来的,显然此时s1!=s2,故两者的hashcode不一定相等。
  • 然而重写了equals,且s1.equals(s2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从Student类重写后的hashcode方法中可以看出,重写后返回的新的哈希值与Student的两个属性有关。
finalize方法

finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。

对象可以被回收,就代表一定会被回收吗?

对于快要dead的线程:

dead的线程
  1. 利用finalize()方法最多只会被调用一次的特性,我们可以实现延长对象的生命周期。
  2. 重写finalize()方法意味着延长了回收对象时需要进行更多的操作,从而延长了对象回收的时间。
  • 对象被回收时,系统会自动调用该对象的 finalize方法 去释放一些资源;子类可重写该方法

  • 即使垃圾回收器工作,finalize方法也不一定得到执行,这是由于程序中的其他线程的优先级远远高于执行finalize()函数线程的优先级。

  • 什么时候被回收:

    Car c = new Car();
    c = null;
    
    • 当某个对象没有任何引用时,jvm会将该对象视为垃圾对象,使用垃圾回收机制来销毁对象。

    • 销毁对象之前会调用该对象的finalize()方法

      • 如果没有重写,则默认调用Object的finalize()方法:

      • protected void finalize() throws Throwable { }
        
      • finalize()方法只有一个****方法体*,里面*没有代码*,是由*protected修饰****的

  • 垃圾回收机制的调用: 由系统(GC算法)决定; 有了垃圾并不会立即回收

    • 主动触发机制: System.gc();

类变量: 静态变量。在类加载时就初始化了,没创建对象也能使用类变量

类方法: 静态方法。不能使用对象的关键字:this,super等

person.age   对象引用.静态变量
  • ​ 只能调用静态变量和其他类方法
main函数:
  • 格式是固定的。
  • 被 jvm所识别和调用。
main函数关键字分析:

public static void main(String[] args)

public: 要让jvm识别到所以权限必须是最大的。
static: 不需要创建对象即可访问main方法。
void: 主函数没有具体的返回值。
main:函数名,不是关键字,只是一个jvm识别的固定的名字。
String[] arg: 这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型的。

  • 默认Java虚拟机创建了new String[0]作为传入参数,长度为0。
  • main函数为什么要传入字符串呢?
    • 因为任何数据都可以通过字符串形式的数据进行转换。、
代码块

什么时候类加载:

  1. 创建对象new
  2. 创建子类对象实例,先加载父类的信息
  3. 使用类的静态成员(静态属性、静态方法)

代码块优先于构造方法的执行

普通代码块:

  • 创建对象时被隐式调用; 创建一次,执行一次

静态代码块:

  • 在类加载时执行,且仅执行一次
  • 作用:对类初始化
final

被final修饰的属性 必须赋初值;且不能被修改

final 的类不能被继承,能实例化

final的方法不能被重写,能继承

for
for(int i = start, j=end; i 

循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,

中间是布尔表达式

循环变量迭代也可以有多条变量迭代 语句,中间用逗号隔开。

String的两种方式

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000275.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号