Java的基础知识

这篇博客是对Java基础知识的总结,涵盖Java基本语法、字符串处理、面向对象特性、集合框架、异常处理和多线程等内容。文章详细讲解了Java的八大基本数据类型、String与StringBuffer/StringBuilder的区别、封装、继承、多态的概念,以及ArrayList与Array的区别。同时,讨论了构造器、this与super的使用,接口与抽象类,并概述了集合中的Collection和Map接口及其常见实现类。此外,还介绍了异常处理的基本概念和线程的生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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有八大基本数据类型,分别是字节、短整型、整型、长整型、字符型、浮点型、双精度型、布尔型

基本数据类型字节取值范围
byte1-2^7 - 2^7-1
short2-2^15 ~ 2^15-1
int4-2^31 ~ 2^31-1
long8-2^63 ~ 2^63-1
char2
float4
double8
boolean4true、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 (!(obj instanceof User)) {
            return false;
        }
        User user = (User) obj;
        return user.userName.equals(userName) && user.userAge == userAge
                && user.userAddress.equals(userAddress);
    }
}
  1. treeSet:提供有序的Set集合
(5.2)Map

Map<k,v>接口,以键值对的形式存储元素(key-value),key是唯一且不可为null,value可为null且有且只有一个为null,value也可重复。

Map的实现类,主要是使用HashMap,下面介绍HashMap的三种遍历方式。

  • for循环(Map.Entry<> e:map.entrySet)
  • entrySet()+iterator
  • keySet()+iterator
public class MapTest {
    public void mapTest(){
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"张三");
        map.put(2,"李四");
        map.put(3,"王五");
        map.put(4,"赵六");
        map.put(5,"张三");
        System.out.println("1.使用for循环进行遍历:");
        for(Map.Entry<Integer,String> entry:map.entrySet()){
            System.out.print(entry.getKey()+":"+entry.getValue()+" ");
        }

        System.out.println();
        System.out.println("2.用迭代器iterator遍历:");
        /**
         *
         *原理:(1)将map集合中的所有键key放到set集合中(key不重复,满足set集合元素不重复规则),
         *     (2)使用迭代器iterator取出每一个键,然后再根据get方法取出每一个键对应的value。
         */
        Set set = map.entrySet();
        Iterator it1 = set.iterator();
        while(it1.hasNext()){
            Map.Entry<Integer,String> map1 = (Map.Entry)it1.next();
            System.out.print(map1.getKey()+":"+map1.getValue()+" ");
        }
	
        System.out.println();
        System.out.println("3.用keySet()迭代遍历:");
        Iterator it = map.keySet().iterator();
        while(it.hasNext()){
            int key;
            String value;
            key = (int)it.next();
            value = map.get(key);
            System.out.print(key+":"+value+" ");
        }
    }

    public static void main(String[] args) {
        MapTest mt = new MapTest();
        mt.mapTest();
    }
}
  • 数组与集合遍历的区别
    数组是基本类型,没有重写toString方法,需要调用Arrays.toString()方法。
    List和集合对象都已经重写了toString方法,因此可以直接打印。
public class Main {
    public static void main(String[] args) {
        int[] arr = {0,1,2,3,4};
        List<Integer> list = new ArrayList<>();
        Set<Integer> set = new HashSet<>();
        Map<Integer,Integer> map = new HashMap<>();
        
        for(int i = 0;i<5;i++){
            list.add(i);
            set.add(i);
            map.put(i,i+1);
        }
        System.out.println("arr输出:"+arr);
        System.out.println("list输出:"+list);
        System.out.println("set:"+set);
        System.out.println("map输出:"+map);
    }
}
输出:
arr输出:[I@1b2c6ec2
arr输出:[0, 1, 2, 3, 4]
list输出:[0, 1, 2, 3, 4]
set输出:[0, 1, 2, 3, 4]
map输出:{0=1, 1=2, 2=3, 3=4, 4=5}

(6)异常

Java异常的结构图如下
异常的结构图
异常主要分为:Error和Exception。

  • Error 错误, 一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等
  • Exception:程序异常,需要使用try,catch代码块捕获。
    public static void main(String[] args) {
        try {
            StudentChild studentChild = new StudentChild();
            studentChild.sayHello();
        }catch (IndexOutOfBoundsException ie){
            System.out.println("数组越界:运行程序时输入的参数个数不够");
        }catch (NumberFormatException ne){
            System.out.println("数字格式异常: 程序只能接收整数参数");
        }catch (ArithmeticException ae){
            System.out.println("算数异常");
        }catch (Exception e){
            System.out.println("未知异常");
            e.printStackTrace();
        }finally {
            System.out.println("不管怎么样,我就是能运行");
            //资源回收代码块
        }
    }

Java 的异常机制主要依赖于try、catch 、finally 、throw 和throws 五个关键字

  • throws:用于方法声明,使用throws 声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理。
  • throw:自行抛出异常,在方法内、代码块中执行。

(7)多线程

创建多线程有三种方式:继承Thread、实现Runnable、使用Callable和Future创建线程

  • 继承Thread类:(1)重写run方法;(2) 创建Mythread实例;(3)调用start方法
public class MyThread extends Thread{
    @Override
    public void run(){
        for(int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }
    public static void main(String[] args) {
        new MyThread().start();
        new MyThread().start();
    }
}
-输出结果-
Thread-1 0
Thread-1 1
Thread-0 0
Thread-1 2
Thread-1 3
Thread-0 1
Thread-1 4
Thread-0 2
Thread-1 5
Thread-0 3
Thread-1 6
Thread-0 4
Thread-1 7
Thread-0 5
Thread-1 8
Thread-0 6
Thread-1 9
Thread-0 7
Thread-0 8
Thread-0 9
  • 实现Runnable接口
public class MyRunnable implements Runnable {

    @Override
    public void run(){
        for(int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }

    public static void main(String[] args) {
        MyRunnable m = new MyRunnable();
        MyRunnable m1 = new MyRunnable();
        new Thread(m).start();
        new Thread(m1).start();
    }
}
//输出
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-1 0
Thread-0 9
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
Thread-1 6
Thread-1 7
Thread-1 8
Thread-1 9
  • 使用Callable和Future
(7.2)线程的生命周期

线程的生命周期:新建、就绪、运行、阻塞、死亡。
 线程的生命周期

(7.3)控制线程
方法名称方法作用
join()让一个线程等待另一个线程完成的方法
sleep()使线程暂停多少毫秒,并使其进入阻塞状态
yield()与sleep类似,但是不会阻塞该线程,只是将该线程转入就绪状态
wait()调用该方法的线程进入waitting状态,只有等待其它线程的通知或被中断才会返回,调用该方法后,会释放对象的锁。
notify()通知一个在对象上的线程,使其从wait()状态返回,返回的前提是该线程获得了对象的锁
总结

以上总结了Java基础的部分内容,对于文章中的不足之处,还请大家批评指正,一起学习!

内容概要:本文详细探讨了基于MATLAB/SIMULINK的多载波无线通信系统仿真及性能分析,重点研究了以OFDM为代表的多载波技术。文章首先介绍了OFDM的基本原理和系统组成,随后通过仿真平台分析了不同调制方式的抗干扰性能、信道估计算法对系统性能的影响以及同步技术的实现与分析。文中提供了详细的MATLAB代码实现,涵盖OFDM系统的基本仿真、信道估计算法比较、同步算法实现和不同调制方式的性能比较。此外,还讨论了信道特征、OFDM关键技术、信道估计、同步技术和系统级仿真架构,并提出了未来的改进方向,如深度学习增强、混合波形设计和硬件加速方案。; 适合人群:具备无线通信基础知识,尤其是对OFDM技术有一定了解的研究人员和技术人员;从事无线通信系统设计与开发的工程师;高校通信工程专业的高年级本科生和研究生。; 使用场景及目标:①理解OFDM系统的工作原理及其在多径信道环境下的性能表现;②掌握MATLAB/SIMULINK在无线通信系统仿真中的应用;③评估不同调制方式、信道估计算法和同步算法的优劣;④为实际OFDM系统的设计和优化提供理论依据和技术支持。; 其他说明:本文不仅提供了详细的理论分析,还附带了大量的MATLAB代码示例,便于读者动手实践。建议读者在学习过程中结合代码进行调试和实验,以加深对OFDM技术的理解。此外,文中还涉及了一些最新的研究方向和技术趋势,如AI增强和毫米波通信,为读者提供了更广阔的视野。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值