Java基础知识

目录                                                               

1、数据类型

2、修饰符总结

  初始化块

3、String总结

4、Java集合(包括数组的知识)

5、File类

  5.1 File类创建和删除功能

  5.2 File类的判断功能

  5.3 File类的获取功能和修改名字功能

  5.4 File类的其它获取功能

6、IO流

  6.1 IO流分类

  6.2  OutputStreamWriter与InputStreamReader

  6.3 打印流

  6.4 对象操作流

7、多线程

  7.1 同步问题

  7.2 线程的生命周期

8、枚举&注解

  8.1 枚举

9、反射 

底部

 

  

 

 

1、数据类型

Java所有关键字都是小写的,TRUE、FALSE和NULL都不是Java关键字。

Java语言支持的类型分为两类:基本类型和引用类型。基本类型包括boolean类型和数值类型。引用类型包括类、接口和数组类型,还有一种特殊的null类型。

字符串不是基本数据类型,字符串是一个类,也就是一个引用数据类型。

如果使用一个巨大的整数值(超过了int类型的表数范围)时,Java不会自动把这个整数当作long类型来处理。如果希望系统将一个整数值当成long类型来处理,应该在这个整数值后增加 l 或者 L 作为后缀。推荐使用  L

Java语言的浮点类型默认是 double类型,如果希望Java将一个浮点类型值当成 float 类型来处理,应该在这个整数值后增加 f 或者 F 作为后缀。

 ----练习:Java生成随机数 

import java.util.Random;
public class myRandom {
public static void main(String[] args) {
Random r = new Random();
// 获取数据范围 [0,10)
int n = r.nextInt(10);
System.out.println(n);
}
}

 

2、修饰符总结
定义类的修饰符:public、final、abstract

定义成员变量的修饰符:public、protected、private、static、final(其中public、protected、private三个最多出现其中一个,可以与static、final组合起来修饰成员变量)
定义方法的修饰符:public、protected、private、static、final、abstract(其中public、protected、private三个最多出现其中一个;final和abstract最多出现其中一个它们可以与static组合起来修饰方法)
定义构造方法的修饰符:public、protected、private三个其中一个

 



final关键字:
  final修饰的类不能被继承,修饰的方法不能被重写,修饰的变量不可以修改成为常量

static关键字:
  它的作用是用于区分成员变量、方法、内部类、初始化块这四种成员到底属于类本身还是属于实例。
  静态的加载优于对象,随着类的加载而加载。所以静态成员不能直接访问非静态成员。static修饰的方法中无法使用this关键字

初始化块
格式: 修饰符只能是 static,使用static修饰的初始化块被称为静态初始化块
  [修饰符] {
   ...
  }

普通初始化块:当创建对象时,系统总是先调用该类里定义的初始化块,然后调用相应的构造器。
当Java创建一个对象时,系统先为该对象的所有实例变量分配内存,接着程序开始对这些实例变量执行初始化,其初始化的顺序是:先执行初始化块或声明实例变量时指定的初始值(按照在代码中的顺序执行),再执行构造器里指定的初始值。

 创建一个java对象时,不久会执行该类的普通初始化块和构造器,而且系统会一直上溯到java.lang.Object类,先执行java.lang.Object类的初始化块,开始执行java.lang.Object的构造器,依次向下执行其父类的初始化块,开始执行其父类的构造器......最后才执行该类的初始化块和构造器,返回该类的对象。


静态初始化块:
负责对类进行初始化

运行结果:静态只初始化一次,先上溯

 

3、String总结

==的作用:比较基本数据类型的值是否相同,比较引用数据类型的地址是否相同

 

用"+"拼接字符串内存示意图

 用"+"做字符串拼接的时候,是将拼接后的字符串新生成一个,原先的会被废弃掉,造成巨大的内存浪费。

StringBuilder了解一下


4、Java集合(包括数组的知识)

需要集中存放多个数据,但数组长度不可变化,且无法保存具有映射关系的数据
常用的集合有哪些? List Set Map
4.1 List

存储的元素有索引,可以重复

4.2 Set


存储的元素无索引,不可以重复,无序状态

4.3 Map

存储键-值对形式的数据,键值不可重复
Map的遍历方法:
利用Map的:方法
 Set<Map.Entry<K,V>> entrySet()
          返回此映射中包含的映射关系的 Set 视图。
然后遍历这个Set集合对象即可,获取到每一个Map.Entry<K,Y>元素,然后调用其

 





并发修改异常 java.util.ConcurrentModificationException
产生原因:在遍历集合的同时对其进行修改
解决办法:不在遍历集合的同时对其进行修改
示例代码:遍历students这个ArrayList集合,并在符合条件时删除其中的元素
for(Student s:students){
if(s.getId().equals(id)){
students.remove(s);
flag = true;
}
}
修改后:用一个下标记录要删除的元素位置
for(Student s:students){
if(s.getId().equals(id)){
index = students.indexOf(s);
flag = true;
}
}

迭代器知识
public interface Iterator<E> :对 collection 进行迭代的迭代器。在对集合进行迭代时,要将其转换为一个迭代器对象进行操作。
Collection中有:可以获得迭代器对象
 Iterator<E> iterator()
          返回在此 collection 的元素上进行迭代的迭代器。
具体到特定的类型,例如List中有:获得迭代器对象
 ListIterator<E> listIterator()
          返回此列表元素的列表迭代器(按适当顺序)。
ListIterator中有add方法,可以实现迭代期间修改列表,从而不引发  并发修改异常   

 

5、File类
文件和目录路径名的抽象表示形式。File类的实例是不可变的;也就是说,一旦创建,File对象表示的抽象路径名将永不改变。
通过指定路径创建File对象时,并不会去检查路径是否存在或者文件是否存在

5.1 File类创建和删除功能

boolean createNewFile():指定路径不存在该文件时时创建文件,返回true;存在时不创建,并返回false

boolean mkdir():当指定的单级文件夹不存在时创建文件夹并返回true,否则返回false 

boolean mkdirs():当指定的多级文件夹某一级文件夹不存在时,创建多级文件夹并返回true,否则返回false

boolean delete():删除文件或者删除单级文件夹      存在时删除并返回true,不存在时返回false     不能删除拥有子文件或者子文件夹的文件夹

 

5.2 File类的判断功能

boolean exists():判断指定路径的文件或文件夹是否存在

boolean isAbsolute():判断当前路路径是否是绝对路径

boolean isDirectory():判断当前的目录是否存在

boolean isFile():判断当前路径是否是一个文件

boolean isHidden():判断当前路径是否是隐藏文件

 

5.3 File类的获取功能和修改名字功能

 File getAbsoluteFile():获取文件的绝对路径,返回File对象

 String getAbsolutePath():获取文件的绝对路径,返回路径的字符串

 String getParent():获取当前路径的父级路径,以字符串形式返回该父级路径

 File getParentFile():获取当前路径的父级路径,以字File对象形式返回该父级路径

 String getName():获取文件或文件夹的名称

 String getPath():获取File对象中封装的路径,绝对就返回绝对,相对就返回相对

 long lastModified():以毫秒值返回最后修改时间

 long length():返回文件的字节数

 boolean renameTo(File dest): 将当前File对象所指向的路径 修改为 指定File所指向的路径,修改的文件不能存在,也就是不能重名

 

5.4 File类的其它获取功能

String[] list():以字符串数组的形式返回当前路径下(必须是文件夹路径)所有的文件和文件夹的名称

File[] listFiles():以File对象的形式返回当前路径下所有的文件和文件夹的名称

static File[] listRoots():获取计算机中所有的盘符

 

 

6、IO流

 

6.1 IO流分类:

  按流向分类:

    输入流:    读取数据  FileReader  Reader

    输出流:    写出数据  FileWriter   Writer

  按数据类型分类:

    字节流:(一次读取一个字节,不能因为有字符流就不需要字节流,因为图片、视频之类的数据底层还是字节流形式)

      字节输入流:    InputStream

      字节输出流:    OutputStream

    字符流:(为了方便一次读取多个字节,比如中文

      字符输入流:    Reader

      字符输出流:    Writer

 

二进制文件(图片、视频、音频等)只能使用字节流

 

6.2 OutputStreamWriter与InputStreamReader

一个案例:利用字符流读取一个文件中的数据在命令行中展示

首先介绍标准的输入输出流:System.in     System.out

查看System的文档

  Static InputStream in

  Static PrintStream out

可以看出标准的输入输出流是字节流

示例代码:

 

import java.io.*;

public class MyIO {
    public static void main(String[] args) {
        BufferedReader br = null;
        OutputStream os = null;
        try {
            // 创建输入流对象
            br = new BufferedReader(new FileReader("test.txt"));
            // 创建输出流对象
            os = System.out;

            String line;
            while ((line=br.readLine()) != null) {
                os.write(line.getBytes());
                os.write("\r\n".getBytes());
            }


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                os.close();
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

从代码处可以看出,标准输出在输出数据时,由于我们获取的数据是字符流获取的,而输出只能是以字节的形式,需要我们将数据转换为字节数组,这样很不方便,那我们需要考虑Java是否提供了一种将字节流转换的工具,使其可以处理字符流,而不是让我们自己手动转换。

这种解决方法就是OutputStreamWriter与InputStreamReader  这两个转换流

 

利用这个类我们对代码进行修改


import java.io.*;

public class MyIO {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
// 创建输入流对象
br = new BufferedReader(new FileReader("test.txt"));
// 创建输出流对象
bw = new BufferedWriter(new OutputStreamWriter(System.out));

String line;
while ((line=br.readLine()) != null) {
bw.write(line);
bw.newLine();
}


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放资源
try {
bw.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
 

 

为了更加方便操作,我们直接将OutputStreamWriter再封装一层,成为BufferedWriter,这里我们就不需要自己再进行字符串转换为字节数组的操作了。

同理也可以对标准输入流转换

 

 6.3 打印流

PrintStream   与   PrintWriter

PrintWriter是一个包装流,字符打印流。

具有写出数据自动刷新(需要在构造方法中设置,并使用特有方法),自动换行(使用println()方法)的特有功能,具体参考API

 

6.4 对象操作流

 详情见Java面向对象 的对象操作流部分

 

7、多线程

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。

所以我认为它们最关键的点就是:是否是『同时』。

如果某个系统支持两个或者多个动作(Action)同时存在,那么这个系统就是一个并发系统。如果某个系统支持两个或者多个动作同时执行,那么这个系统就是一个并行系统。并发系统与并行系统这两个定义之间的关键差异在于“存在”这个词。

在并发程序中可以同时拥有两个或者多个线程。这意味着,如果程序在单核处理器上运行,那么这两个线程将交替地换入或者换出内存。这些线程是同时“存在”的——每个线程都处于执行过程中的某个状态。如果程序能够并行执行,那么就一定是运行在多核处理器上。此时,程序中的每个线程都将分配到一个独立的处理器核上,因此可以同时运行。

我相信你已经能够得出结论——“并行”概念是“并发”概念的一个子集。也就是说,你可以编写一个拥有多个线程或者进程的并发程序,但如果没有多核处理器来执行这个程序,那么就不能以并行方式来运行代码。因此,凡是在求解单个问题时涉及多个执行流程的编程模式或者执行行为,都属于并发编程的范畴。

摘自:《并发的艺术》 — 〔美〕布雷谢斯
实现多线程的方法1:继承Thread类
public class MyThread {
    public static void main(String[] args) {
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();
        t1.setName("one");
        t2.setName("two");
        t1.start();
        t2.start();
    }
}

-----------------------------------
public class Thread1 extends Thread {
    @Override
    public void run() {
        for(int i=0; i<100; i++) {
            System.out.println(super.getName() + ":" + i);
        }
    }
}
-----------------------------------
public class Thread2 extends Thread{
    @Override
    public void run() {
        for(int i=0; i<100; i++) {
            System.out.println(super.getName() + ":" + i);
        }
    }
}

 实现多线程的方法2:实现Runable接口

public class MyRunable {
    public static void main(String[] args) {
        Runable1 r1 = new Runable1();
        Thread t1 = new Thread(r1);
        t1.start();

        Thread t2 = new Thread(r1);
        t2.start();
    }
}
-------------------------------------------
public class Runable1 implements Runnable {
    @Override
    public void run() {
        for(int i=0; i<100; i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

 

为什么会有继承Thread类实现多线程和实现Runable实现多线程两种方法呢?

主要是因为Java的单一继承,如果我们继承了Thread类后还想继承其他类,显然是做不到的,但实现Runable接口便还可以继承其他类,所以推荐使用第二种方法

 

7.1 同步问题:synchronized()

涉及到多线程必然会涉及到同步问题,也就是对于共享资源,同一时刻只能有一个线程进行访问。

synchronized可以用来修饰代码块和方法

非静态方法的锁对象是this,静态方法的锁对象是当前类的字节码对象

 

 

7.2 线程的生命周期

 

 

 

8、枚举&注解

8.1 枚举

自定义枚举类

class Season{
private final String seasonName;
private final String seasonDesc;

private Season(String seasonName, String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc =seasonDesc;
}

public static Season SPRING = new Season("Spring", "春天");
public static Season SUMMER = new Season("Summer", "夏天");
public static Season AUTUMN = new Season("Autumn", "秋天");
public static Season WINTER = new Season("Winter", "冬天");

public String getSeasonName() {
return seasonName;
}

public String getSeasonDesc() {
return seasonDesc;
}

@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}

利用关键字:enum

public enum Season {
SPRING("spring","春天"),
SUMMER("summer","夏天"),
AUTUMN("autumn","秋天"),
WINTER("winter","冬天");

private final String seasonName;
private final String seasonDesc;
private Season(String seasonName, String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}

public String getSeasonName() {
return seasonName;
}

public String getSeasonDesc() {
return seasonDesc;
}

@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}

 

9、反射

java.lang.Class是反射的源头,我们创建了一个类,通过编译(java.exe),生成对应的.class文件、之后我们使用java.exe加载(JVM的类加载器)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存放在缓存区,这个类本身就是一个Class的实例

具体内容见:Java反射






posted @ 2019-01-16 10:21  潘_磊  阅读(221)  评论(0编辑  收藏  举报