Java的基础知识 - Go语言中文社区

Java的基础知识


Java基础知识(第一部分)

在初学Java的过程中,一直在漫无目的看书写代码,最近一段时间,想把以前的内容回过头来总结一遍,温故而知新,也是对Java基础知识再次学习。

一、总体架构

以书籍的目录为例,市场上大多数的Java书籍从两部分来阐述Java的内容,第一部分则是Java的基础知识,而第二部分则是Java的深入部分。今天就将Java的基础部分进行一个简单的总结。首先,它的大体框架如下:

(1)Java基本语法(基本数据类型、数组的建立)
(2)字符串(String、StringBuffer、StringBuilder)
(3)面向对象之三国鼎立(封装、继承、多态)(Java的核心)
(4)面向对象之群雄争霸
(5)集合的楚汉争霸(Collection、Map)
(6)异常(Throwable)
(7)多线程(Thread、Runnable)

二、内容讲解

(1)Java基本语法

(1.1)基本数据类型

Java有八大基本数据类型,分别是字节、短整型、整型、长整型、字符型、浮点型、双精度型、布尔型

基本数据类型 字节 取值范围
byte 1 -2^7 - 2^7-1
short 2 -2^15 ~ 2^15-1
int 4 -2^31 ~ 2^31-1
long 8 -2^63 ~ 2^63-1
char 2
float 4
double 8
boolean 4 true、false
(1.2)数组的建立
基本数据类型[] 数据名 = new 基本数据类型[定义数组的长度]
以整型数据为例,创建数组从语法上来说两步走
	(1)定义个数组的引用变量
	(2)将创建的数组赋给这个引用变量,也就是这个引用指向它
int[] arr;
arr = new int[10];
//合起来就是
int[] arr = new int[10];
//此时初始化数据

由于传统建立的数据需要初步定义好数组的长度,因此创建数组长度过小则会不够保存数据,而数组长度过大则会导致浪费资源的现象,因此动态数组ArrayList则比传统数组更有优势,这一点会在集合部分进行介绍。除此之外,字符串String.toCharArray()也能够转换为字符数组,这个方法在很多编程题中用到,因此,贴上此方法的源码:

public char[] toCharArray() {
        return this.isLatin1() ? StringLatin1.toChars(this.value) : StringUTF16.toChars(this.value);
    }

(2)字符串

(2.1)String

线程安全不可变的字符串

  1. String类包含许多方法使用String类最大特性是不可变性,因此要使用String.split()时要赋予新的String对象。
  2. String.toCharArray()将String对象转换为字符数组
	public static void main(String[] args) {
        String str="abcde";
        char[] ch = str.toCharArray(); //ch{a,b,c,d,e}
    }
  1. String.charAt(int index)方法,获取字符串的单个字符
  2. String.valueOf(int i),获取int型的字符串
  3. String.length(),获取字符串的长度
(2.2)StringBuffer

线程安全可变的字符串,效率低于StringBuilder

  1. append()方法,写入数据
  2. charAt()返回指定索引的数据
  3. reverse,字符串翻转
  4. toString,返回字符串
(2.3)StringBuider

线程不安全的可变字符串,但是效率高于StringBuffer,其使用方法与StringBuffer一样

  1. append()方法,写入数据
  2. charAt()返回指定索引的数据
  3. reverse,字符串翻转
  4. toString,返回字符串

(3)面向对象之三国鼎立

在面试的过程中,很多面试官会首先问Java面向对象的特点是什么?(答:封装、继承和多态)那你回答一下什么是封装、继承和多态,以及它们的使用场景?(答:…)

(3.1)封装

Java提供了四个修饰符来保护Java类中的成员变量、方法不受外界所破坏,这四个访问修饰符如下所示:

访问修饰符 访问权限
public 全局范围
protected 子类及同一包的类
默认(空) 同一包中的类
private 同一个类中

一般来说,使用private来封装类中的成员变量的时候,这个成员只能在当前类的内部被访问,该类会提供set、get方法来供其它类进行调用。

//用户类
public class User {
    private String name;
    private int id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
//----------------------------------------------
//学生类
public class Student {
    public String name;
    public int id;
}
//测试类
public class Test {
    public static void main(String[] args) {
        User user = new User();
        Student student = new Student();
        String name = student.name;
        String uname = user.name;//这行会报错,因为User类的name变量是私有的。外部类无法访问
         //以下是正确的调用
        user.setName("张三");
        System.out.println(user.getName());
    }
}
(3.2)继承

Java只能单继承,其继承关键字为extends

public class Student {
    public String name;
    public int id;
    
    public void sayHello(){
        System.out.println("Hello");
    }
}

public class StudentChild extends Student {

    public void sayHelloAlso(){
        super.sayHello();
        System.out.println(super.name);
        System.out.println(super.id);
    }

    @Override
    public void sayHello(){
        System.out.println("GoodBye");
    }
    public static void main(String[] args) {
        StudentChild studentChild = new StudentChild();
        studentChild.sayHelloAlso();
        studentChild.sayHello();
    }
}
//输出
Hello
null
0
GoodBye

总结:子类继承父类能够得到父类的成员变量和方法,子类中的方法可以用关键字super.成员变量或方法来得到父类的成员变量或方法,当父类的方法不满足子类的需求时,子类可以重写父类的方法,方法重写(Override)需要满足“两同两小一大”原则。

  • 两同:方法名与参数列表都相同
  • 两小:返回值类型、抛出的异常
  • 一大:访问权限类型
(3.2)多态

首先介绍一下Java引用变量的类型,其包括编译时的类型和引用时的类型。

  • 编译时类型:由声明变量时使用的类型所决定
  • 运行时类型:实际赋给该变量的对象所决定

多态的场景:当编译时类型与运行时类型不一致时,此时就会发生多态情况。例如,下面程序的
Student s1 = new StudentChild(); 子类和父类都包含sayHello()方法,当s1调用sayHello方法时,会运行子类的sayHello方法。父类的引用变量指向子类的对象。
相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,这就是多态。
总结:编译看左边,运行看右边,运行一个Java程序的时候,javac会首先编译.java程序为 .class文件,当编译的时候识别出左边的变量是否包含该变量所调用的方法,若包含该方法,则编译通过,Jvm会将编译的.class文件进行加载给机器能够识别的语言;反之,编译失败,则JVM无法识别出.class文件。

public class Student {
    public String name;
    public int id;

    public void sayHello(){
        System.out.println("Hello");
    }
    public void noByeBye(){
        System.out.println("Bye");
    }
}

public class StudentChild extends Student {

    public void sayHelloAlso(){
        System.out.println(super.name);
        System.out.println(super.id);
        super.sayHello();
    }
    public void sayHello(){
        System.out.println("GoodBye");
    }
    public static void main(String[] args) {
        Student s1 = new StudentChild();
        s1.sayHello();
    }
}
//输出
GoodBye
Hello

(4)面向对象之群雄逐鹿

(4.1)构造器与初始化
  1. 构造器是为了初始化类中的成员变量
  2. 构造器无返回值,不能声明为void,一般为public
  3. 构造器方法名相同,参数列表不同,就会形成重载
  4. 在构造器中调用其它方法,直接调用方法名即可;在构造器中调用其它构造器,需要this(方法名),且必须在第一行
  5. 当在构造器中调用父类的构造方法时,使用super(方法名),必须在程序第一行
(4.2)this与super
  1. this关键字用的比较多的是局部变量给成员变量赋值
public class Student {
    public String name;
    public int id;

    public Student(String name,int id){
        this.name = name;
        this.id = id;
    }

    public void sayHello(){
        String name = "小明";
        System.out.println(this.name+"你好");
    }

    public static void main(String[] args) {
        Student student = new Student("小王",17);
        student.sayHello();
    }
}
//输出
小王你好
  1. super子类调用父类的方法或成员变量
public class ChildTest extends FatherTest {

    public void sayHello(){
        System.out.println("子类调用父类的方法");
        super.sayBye(super.name,super.id);
        //super.sayBye(name,id);这种方法也一样,可以省略super

    }
    public static void main(String[] args) {
        ChildTest childTest = new ChildTest();
        childTest.sayHello();
    }
}

public class FatherTest {
    String name = "小明";
    int id = 1;

    public void sayBye(String name,int id) {
        System.out.println(id + ":"+ name +" "+ "byebye!");
    }
}
//输出
子类调用父类的方法
1:小明 byebye!
(4.3)抽象类与接口
  1. 抽象类
  • 抽象类必须要有关键字abstract修饰
  • 抽象类中含有抽象方法和普通方法
  • 抽象类中的成员变量随意修饰
public abstract class AbstractTest {
    public static final int tel = 456123156;
    private int id;
    int num;
    protected int hands;
    public String name;
    public void sayHello(){
        System.out.println("This is a abstract class");
    }
    public abstract void say();
}
  1. 接口
  • 接口中的方法必须为抽象方法,且修饰符为public 或者默认不写
  • 接口中的变量必须为public static final类型,一般不用写,系统会自动识别。
  • 接口中的变量必须初始化。
public interface InterfaceTest {

    public static final int id =1;
    public abstract void say();
    abstract void speak();
}

(5)集合的楚汉争霸

Java集合分为两大阵营:Collection集合和Map集合。老规矩,从全局观进入学习,先附上一张集合的全局结构图
集合的总体结构图

(5.1)Collection

Collection:属于集合,继承于Iterable

public interface Collection<E> extends Iterable<E>
  • List:它是接口,继承Collection集合,要实现List接口,可以创建接口的引用变量来指向ArrayList对象或者LinkedList对象。特点:有序,元素可重复。
public interface List<E> extends Collection<E>
  1. ArrayList
    继承AbstractList,实现List接口,底层由数组来实现的,包含了数组的特点,查询快,增删慢。
  2. LinkedList
    继承AbstractSequentialList,实现List接口,底层是有链表实现的,查询慢,增删快。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CollectionTest {
    //List集合的增删改查
    public void listTest(){
        List<Integer> list = new ArrayList<>();
        //添加数据(增)
        for(int i = 0;i<10;i++){
            list.add(((int)Math.floor(Math.random()*i)));
        }
        //遍历list(查)
        System.out.println("生成的原始随机数组:");
        //System.out.println("使用foreach遍历集合:");
        for(Integer i:list){
            System.out.print(i+" ");
        }
        //删除集合中的元素
        System.out.println();
        list.remove(2);
        System.out.println("将list中的第3个元素删除");
        //System.out.println("使用for循环遍历集合:");
        for(int i = 0;i<list.size();i++){
            System.out.print(list.get(i)+" ");
        }
	//更改集合中的元素
        System.out.println();
        list.set(0,1);
        System.out.println("将集合中第一个元素改为1");
        //System.out.println("使用Iterator遍历集合:");
        Iterator it= list.iterator();
        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }
    }
    public static void main(String[] args) {
        CollectionTest collectionTest = new CollectionTest();
        collectionTest.listTest();
    }
}

测试结果:
生成的原始随机数组:
0 0 1 2 2 3 2 2 4 1 
将list中的第3个元素删除
0 0 2 2 3 2 2 4 1 
将集合中第一个元素改为1
1 0 2 2 3 2 2 4 1 
Process finished with exit code 0
  • Set:接口,继承Collection集合。特点:无序,元素不可重复。
public interface Set<E> extends Collection<E>
  1. HashSet:采用哈希表结构存储数据,它是通过判断hashcode和equals方法来保证元素的唯一性。
    原理:先判断hashcode值,若相同,在判断equals()内容是否相同,若相同,则不会将该对象存储。
    由于hashcode是Object类的方法,任何类都是Object的子类,因此任何类都含有hashcode方法。
    (1)首先,当向哈希表存放对象时,会调用对象的hashcode方法从而算出对象存放在哈希表中的(2)其次,当算出的hashcode值与另一个对象相同时,这个时候会发生“哈希冲突”,此时会调用对象的equals方法来比较两个对象的内容是否相同从而判定是不是同一个对象。
    (3)最后,如果equals方法返回的是true,则不会把新增的对象存放在哈希表中,如果为false,则把新增的对象存放在哈希表中。
    注意:对于HashSet,当HashSet存储元素是JAVA API提供的类型元素时,此时不需要重写hashcode与equals方法;当HashSet存储元素是自定义的元素时,则必须重写HashCode与equals方法。
/**
 * Set集合是无序的,元素不可重复的
 */
//当HashSet存储Java API提供的元素时,此时不需要重写hashcode与equals方法。
public class HashSetTest {
    public void hashSet(){
        HashSet<User> set = new HashSet();
        set.add(new User("张三",18,"南京"));
        set.add(new User("李四",19,"上海"));
        set.add(new User("王五",20,"合肥"));
        set.add(new User("赵六",17,"杭州"));
        Iterator<User> it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    public static void main(String[] args) {
        HashSetTest hash = new HashSetTest();
        hash.hashSet();
    }
}

/**
 * 创建User实体类,并重写hashcode和equals方法
 */
public class User {
    private String userName;
    private int userAge;
    private String userAddress;
    public User(String userName,int userAge,String userAddress){
        this.userName = userName;
        this.userAge = userAge;
        this.userAddress = userAddress;
    }
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getUserAge() {
        return userAge;
    }

    public void setUserAge(int userAge) {
        this.userAge = userAge;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }
    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + ''' +
                ", userAge=" + userAge +
                ", userAddress='" + userAddress + ''' +
                '}';
    }

    @Override
    public int hashCode() {
        int result = 1;
        result = result * 31 + userAge;
        result = result * 31 + ((userName == null) ? 0 : userName.hashCode());
        result = result * 31 + ((userAddress == null) ? 0 : userAddress.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (
                        
                        
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u010019566/article/details/99582943
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢