Java知识点

Java浅拷贝

Java的深拷贝和浅拷贝 - YSOcean - 博客园 (cnblogs.com)

Clone 是 Object 类中的一个方法,通过对象A.clone() 方法会创建一个内容和对象 A 一模一样的对象 B,clone 克隆,顾名思义就是创建一个一模一样的对象出来(浅拷贝)。

package com.JavaCour;
public class HelloWorld {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person("zhangsan",21);
        p1.setAddress("湖北省", "武汉市");
        Person p2 = (Person) p1.clone();
        System.out.println("p1:"+p1);
        System.out.println("p1.getPname:"+p1.getPname().hashCode());

        System.out.println("p2:"+p2);
        System.out.println("p2.getPname:"+p2.getPname().hashCode());

        p1.display("p1");
        p2.display("p2");
        p2.setAddress("湖北省", "荆州市");
        System.out.println("将复制之后的对象地址修改:");
        p1.display("p1");
        p2.display("p2");
    }
}

Java类的static方法

当运行java程序的时候,java中的类方法就分配了入口地址,所以可以不创建对象就直接访问。

toString()方法

很像c++cout<<的重载,返回反映这个对象的字符串

import方法

比如:

cn.ahut.test.A a = new cn.ahut.text.A();

在这里包的名字过长,使用import cn.ahut.test.A;

这样这个变量就可以改变写法为:A a = new A();//非常的方便

java系统包的常见的方法

(2条消息) Java基础类库(系统包)_软件开发技术爱好者的博客-CSDN博客_java系统包

Java.lang

有Java自动调用,不需要导入,经常使用的类:Object, System, Runtime, Math, String, StringBuffer等。

Object的介绍:它是所有类的父类,一个类没有指定父类,就会默认继承该类,可以new一个Object类。

方法:clone(), equals(), hashCode(), toString(), getClass(), 还有几个线程和垃圾回收的类。

System的简介:该类是private修饰,所以不可以new一个System类,提供了标准输入、输出和错误输出的变量,还有一些静态方法。

方法:

public final static InputStream in; //标准输入流

public final static PrintStream out; //标准输出流

public final static PrintStream err; //标准错误流

其中System.out和System.err都被包装成了一个PrintStream,使用起来比较方便;但是System.in不一样,不可以直接处理数据,需要其他类一起处理。

System.in是一个很原始、很简陋的输入流对象,因为只能按字节读取,返回值是占一个字节的整形数据

Scanner in = new Scanner(System.in); String name = in.nextLine();

InputStream in = System.in; byte[] b = new byte[1024]; int len = in.read(b); Sout(new String(b, 0, len));

BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String s = in.readLine();

System的其他常用的方法:

System.arrayCopy(src, startSrc, dest, startDest, endDest);

System.currentTimeMillis();//返回毫秒数

**Math类简介:**final的,提供多种数学方法,并且该类中所有的方法都是静态的,

常用的方法:Random(),产生0-1之间的数字,sqrt(),abs(),pow()

字符串类:String和StringBuffer

Java.util

Date, Scanner

Date的常用方法:after、before、clone、compareTo、hashCode、getTime、setTime、toString、valueOf

String的常用方法

s1.equals(s2);

s1.equalsIgnoreCase(s2);//忽略大小写

“Hello”.contains(“ll”); // true

“Hello”.substring(2, 4);//“llo”

“hello”.indexOf(“l”);// 2

s1.isEmpty();//字符串长度是否为空

s1.isBlank();//是否是空串,如"\n";

String s = "I am a 123!";
byte b[] = s.getBytes();
// 73 32 97 109 32 97 32 49 50 51 33 
String s = "A, b, c, d";
String[] ss = s.split("\\,");

StringBuider

动态字符串,可以修改的字符串

判断汉字

汉字基本集中在[19968,40869]之间,共有20901个汉字

unicode编码范围:

汉字:[0x4e00,0x9fa5](或十进制[19968,40869])

char c;

if(c>=“\u4e00” && c<=“\u9fa5”){c就是汉字};

public class ImportTest {
    public static void main(String[] args) {
        String s = new String("2022年 9月14日 , , 12239 qwerr");
        int l=0;
        int num=0;
        String s1="", s2="";//s1是存储数字字符串,s2是存储汉字字符串。
        for(int i=0; i<s.length(); i++){
            Character c = new Character(s.charAt(i));
            l=0;
            while(Character.isDigit(c)){
                i++;
                c = new Character(s.charAt(i));
                l++;
            }
            s1 += s.substring(i-l, i);
            l=0;

            while(String.valueOf(c).matches("[\u4e00-\u9fa5]")){
                i++;
                c = new Character(s.charAt(i));
                l++;
            }
            s2 += s.substring(i-l, i);

        }
        System.out.println(s1);
        System.out.println(s2);
    }
}

Java提供的常用工具类

  • Math:数学计算

  • Random:生成伪随机数

    •   public class TestAll {
            public static void main(String... args) {
                Random random = new Random(22);
                Random random1  = new Random(21);// 如果是同一个种子,生成的随机数字是相同的
                System.out.println(random1.nextInt(10)+" "+random.nextInt());//nextInt(10)==>[0, 10);
                System.out.println(random1.nextBoolean()+" "+random.nextBoolean());
                System.out.println(random1.nextDouble()+ " "+random.nextDouble());
            }
        }
        @Test
            public void RandomNextIntDemo3(){
                Random r = new Random();
                int n3 = r.nextInt(11);//左闭右开
                int n4 = Math.abs(r.nextInt() % 11);
                System.out.println("n3:"+n3);
                System.out.println("n4:"+n4);
            }
      
  • SecureRandom:生成安全的随机数

继承

向上转型与向下转型:upcasting,downcasting;

  • 子类的构造方法可以通过super()调用父类的构造方法;

  • 可以强制向下转型,最好借助instanceof判断;

接口

default关键字可以让子类不用复写父类接口的这个方法。

package com.JavaCour;

public class JavaCourse {

    public static void main(String[] args) {
        Per p = new Per("123");
        System.out.println(p.getName());
        p.run();
    }

}
interface PersonInterface{
    default void run(){
        System.out.println("run");
    }
    String getName();
}
class Per implements PersonInterface{
    String name;
    Per(String name){
        this.name=name;
    }
    public String getName(){
        return "123";
    }
}

范型

即模板Template

Java泛型类型擦除以及类型擦除带来的问题

Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息(就是Template会变成Object)都会被擦掉。

擦掉之后变成原始类型(object)

所以不能用类型参数替换基本类型。就比如,没有ArrayList<double>,只有ArrayList<Double>。因为当类型擦除后,ArrayList的原始类型变为Object,但是Object类型不能存储double值,只能引用Double的值。

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("abc");

        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(123);

        System.out.println(list1.getClass() == list2.getClass());//true
    }
}

使用范型数据的时候只能使用封装的类。

原始类型封装类
booleanBoolean
charCharacter
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble

JavaDoc

该命令可以自动为我们生成JavaDoc标准文档,

在命令行下面
javaDoc Java.java

会生成一个index.html,打开之后发现里面会有很详细的写的类的说明文档。

@auther

@version

@since

@param

@return

@throws

Java多态注意事项

1、多态指的是方法的多态,属性没有多态,多态的意思是指同一个方法可以通过不同对象的引用去调用。

2、父类和子类是有联系的,否则报异常,CalssCastException

3、存在条件:继承关系的出现,Father f = new Son()

有一些方法不可以重写:static、private、final

	Father f = new Father();
	Son s = (Son)f;
	s.disPlay();

·Exception in thread “main” java.lang.ClassCastException: com.JavaCour.Father cannot be cast to com.JavaCour.Son

package com.JavaCour;

import java.util.Calendar;
import java.util.Date;

public class CalendarTest {
    public static void main(String[] args) {
        Father f = new Son();
//        Son s = (Son) new Father();
        Son son = new Son();
        f.disPlay();
        son.disPlay();
    }
}
class Father{
    String name;
    Father(){
        this.name = "";
    }
    Father(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void disPlay(){
        System.out.println("I am your father!");
    }
}
class Son extends Father{
    int age;
    Son(String name, int age){
        super(name);
        this.age = age;
    }
    Son(){
        this.name="";
        this.age=0;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public void disPlay(){
        System.out.println("I am your son!");
    }
}

测试冒泡排序的速度

public static void main(String[] args) {
    int a1=50000;
    int a=2000;
    Calendar calendar = Calendar.getInstance();
    //        System.out.println(calendar.getTimeInMillis());
    int[] array = new int[50000];
    for(int i=0; i<a1; i++){
      array[i]=(int)(Math.random()*100);
    }
    long start = calendar.getTimeInMillis();
    for(int i=0; i<a1; i++){
      for(int j=i+1; j<a1; j++){
        if(array[i]>array[j]){
          int temp = array[i];
          array[i] = array[j];
          array[j] = temp;
        }
      }
    }
    calendar.setTime(new Date());
    //        System.out.println(calendar.getTimeInMillis());
    long end = calendar.getTimeInMillis();
    System.out.println(end-start);
}

Java的反射

大白话说Java反射:入门、使用、原理

Java反射的解释:可以在程序运行期间获取类的信息,利用反射机制的类:Class,Fliect

正射:Peoson p = new Person();

反射:非常复杂,不好写,要用到forName()方法,

Java匿名类

匿名内部类实现接口

Java匿名类的出现:接口的实现或父类的子类只需要使用一次的时候,

这个时候可以直接定义一个内部实现类,实现接口或者继承父类。

package com.JavaCour;
public class HelloWorld {
    public static void main(String[] args){
        Score s = new Score(){
            @Override
            public double getAverageScore() {
                System.out.println("定义了一个变量的匿名接口");
                return 0;
            }
        };
        s.getAverageScore();
        new Score(){
            @Override
            public double getAverageScore(){
                System.out.println("直接调用的匿名接口");
                return 0;
            }
        }.getAverageScore();
    }
}

Java正则表达式

单个字符匹配:

正则表达式规则可以匹配
A指定字符A
\u548c指定Unicode字符
.任意字符ab&0
\d数字0~90~9
\w大小写字母,数字和下划线a`z`,`A`Z0~9_
\s空格、Tab键空格,Tab
\D非数字aA&_,……
\W非\w&@,……
\S非\saA&_,……

复杂匹配的规则:

正则表达式规则可以匹配
^开头字符串开头
$结尾字符串结束
[ABC][…]内任意字符A,B,C
[A-F0-9xy]指定范围的字符A,……,F0,……,9xy
[^A-F]指定范围外的任意字符A~F
AB|CD|EFAB或CD或EFABCDEF

主要是两个类的使用:Pattern,Matcher。

Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(String regex)简单工厂方法创建一个正则表达式。返回值就是regex

Pattern.matcher(CharSequence input)返回一个Matcher对象.
Matcher类的构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例。

Matcher有几个常用的方法:find(), matches(), start(), end(), group().

find():是否存在与该模式匹配的下一个子序列。简单来说就是在字符某部分匹配上模式就会返回true,同时匹配位置会记录到当前位置,再次调用时从该处匹配下一个。

matches():整个字符串是否匹配上模式,匹配上则返回true,否则false。完全匹配

Matcher中的start()和end()。start(),点进方法可以看到返回的是上一个匹配项的起始索引,如果没有匹配项将抛出IllegalStateException异常。同理,end()则为结束的索引。

Matcher中的group()返回值是匹配好的字符串,Matcher.group(index)返回值是匹配部分的子串,如1代表第一个子串。

public class HelloWorld {
    public static void main(String[] args){
        String s = "23:01:59";
        String regex = "([0-9]{2}):([0-9]{2}):([0-9]{2})";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(s);
        if(m.matches()){
            System.out.println(m.group(1));
            System.out.println(m.group(2));
            System.out.println(m.group(3));

        }
    }
}

匹配电话号码:

package com.JavaCour;


import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CalendarTest {
    public static void main(String[] args) {
        String regex = "[1-9][0-9]{10}";
        Pattern p = Pattern.compile(regex);
        System.out.println(p);
        Matcher m = p.matcher("123456789011234567890112345678901");
//        System.out.println(m.find());
        System.out.println(m.matches());

        while(m.find()){
            String match = m.group();
            System.out.println(m.start()+"->"+m.end());
            System.out.println(match);
        }
    }
}
[1-9][0-9]{10}
false
11->22
12345678901
22->33
12345678901

示例中没有第一个0->11的串:因为前面matches()方法改变了匹配字符串的索引,将索引改成了11->22.

BigInteger

大数运算之-Java-BigInteger-的基本用法

StringTokenizer

StringTokenizer

字符串分词器,和String的split比较相似,有三个重载方法:常用方法里都有Token这个单词

    1. StringTokenizer(String str) :指定默认的分隔符,有空格(“”)、制表符(\t)、换行符(\n)、回车符(\r)。
    1. StringTokenizer(String str, String delim) :用一个指定的分隔符delim。
    1. StringTokenizer(String str, String delim, boolean returnDelims) :用一个指定的分隔符delim,同时,指定是否返回分隔符。

ArrayList

package com.JavaCour;

import java.util.*;

public class HelloWorld {
    public static void main(String[] args) {
        // get foreach iterator
        ArrayList<Person> array = new ArrayList<Person>(10);
        Person p1 = new Person("122", 2);
        Person p2 = new Person("122", 6);
        Person p3 = new Person("122", 4);
        Person p4 = new Person("122", 1);
        Person p5 = new Person("122", 9);
        Person p6 = new Person("122", 100);
        Person p7 = new Person("122", 20);
        array.add(p1); array.add(p2);
        array.add(p3); array.add(p4);
        array.add(p5); array.add(p6);
        array.add(p7);
        array.remove(0);
        array.set(1, new Person("123", 23));

        Iterator<Person> iter = array.iterator();
        System.out.println("Iterator:");
        while(iter.hasNext()){
            System.out.println(iter.next());
//            iter.next();
        }
        System.out.println("Get:");
        for(int i=0; i<array.size(); i++){
            System.out.println(array.get(i));
        }
        System.out.println("Foreach:");
        for(Person p:array){
            System.out.println(p.toString());
        }
        System.out.println("Sort:");
        Collections.sort(array);
        for(Person p:array){
            System.out.println(p.toString());
        }
    }
}

HashMap

package com.JavaCour;

import java.util.*;

public class HelloWorld {
    public static void main(String[] args) {
        Map<String , String> m = new HashMap<String, String>();
        m.put("1", "value1");
        m.put("2", "value2");
        m.put("3", "value3");
        System.out.println("1.......Use keySet():");
        for(String key: m.keySet()){
            System.out.println("key:"+key+" value:"+m.get(key));
        }
        System.out.println("2........entrySet iterator :");
        Iterator<Map.Entry<String, String>> iter = m.entrySet().iterator();
        while(iter.hasNext()){
            System.out.println(iter.next());
        }
        System.out.println("3........entrySet :");
        for(Map.Entry<String, String> entry: m.entrySet()){
            System.out.println("key: "+ entry.getKey()+" Value:"+entry.getValue());
        }
        System.out.println("4..............Map.values():");
        for(String value:m.values()){
            System.out.println("Value: "+value);
        }
    }
}

Java 集合框架

Collections

img

顶层的都是一些Interface,下面的具体的每一个都是继承它们。

主要包括两种类型的容器:

  • Collections
  • Map

Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayListLinkedListHashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。

Map也属于Collection,都是存储数据的。

Java Swing的简单使用

Java Swing有5种布局方式:BorderLayout(边界布局)、FlowLayout(流式布局)、BoxLayout(盒子布局)、GridLayout(网格布局)、null(空布局)

使用panel和Container显示一些控件,下面显示的是用户名和密码的简单的验证。

package com.JavaCour;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class HelloWorld extends JFrame{
    public static void main(String[] args) {
        new HelloWorld();
    }
    JPanel panel;
    Container cp;
    JTextField jTextField;
    JPasswordField jPasswordField;
    JButton jButton;
    JButton jButton1;
    public HelloWorld(){
      	// 设置定位
        JLabel label = new JLabel("用户");label.setBounds(20, 20, 80, 30);
        JLabel label1 = new JLabel("密码");label1.setBounds(20, 70, 80, 30);
        jTextField = new JTextField();jTextField.setBounds(50, 20, 80, 30);
        jPasswordField = new JPasswordField();jPasswordField.setBounds(50,  70, 80, 30);
        jButton = new JButton("登录");jButton.setBounds(20, 120, 60, 30);
        jButton1 = new JButton("清空");jButton1.setBounds(90, 120, 60, 30);
	    // 添加事件的监听
        jButton1.addActionListener(new Listen());
        jButton.addActionListener(new JButtonListen());

        panel = new JPanel();
        panel.setLayout(null);// 设置水平布局,而且设置了水平布局label等的setBounds才有作用
        panel.add(label);
        panel.add(label1);
        panel.add(jTextField);
        panel.add(jPasswordField);
        panel.add(jButton);
        panel.add(jButton1);

        cp = this.getContentPane();
        cp.add(panel);

        this.setTitle("登录");
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//点击X程序退出,否则会一直运行
        this.setSize(800, 600);
        this.setBounds(200, 300, 200, 200);//设置定位
        this.setVisible(true);
    }
  	//实现登录和密码框的清空的监听器
    public class Listen implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            jTextField.setText("");
            jPasswordField.setText("");
        }
    }
  	// 实现登录成功按钮的dialog
    public class JButtonListen implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if(jTextField.getText().equals("黄志缘") && jPasswordField.getText().equals("123456")) {
                JOptionPane.showMessageDialog(null, "成功");
            } else {
                JOptionPane.showMessageDialog(null, "失败");
            }
        }
    }
}

读写文件

读文件

1、

BufferedReader new一个FileReader对象,然后利用BufferedReaderreadline方法一行一行读取。

public static void main(String[] args) {
  try{
    BufferedReader in = new BufferedReader(new FileReader("D:\\AA-Idea\\JULItheima\\src\\main\\java\\com\\JavaCour\\123.html"));
    String str;
    while((str=in.readLine())!=null){
      System.out.println(str);
    }
  }catch(Exception e){
    System.out.println(e);
  }
}
@Test
public void readFile02() throws IOException {
  String path = "D:\\AA-Idea\\JULItheima\\src\\main\\java\\com\\JavaCour\\123.html";
  Stream<String> lines = Files.lines(Paths.get(path));
  lines.forEach(ele ->{
    System.out.println(ele);
  });
  //  lines.forEachOrdered(System.out::println);
}

2、

b的 getByte方法是将字符串编码为 byte 序列,https://www.runoob.com/java/java-string-getbytes.html

out 是一个 FileOutputStream对象,将b写入流,in 是一个FileInputStaeam流对象,利用in.read从流中读取数据,一次两个字节。在这个过程中b,只是作为一个缓冲对象,read之后改变b的前两位。

基本文件字节流FileInputStream、FileOutputStream:https://juejin.cn/post/7002410593625833479

@Test
public void readFile03(){
    String path = "D:\\AA-Idea\\JULItheima\\src\\main\\java\\com\\JavaCour\\123.html";
    File file = new File("path");
    byte[] b = "欢迎welcome".getBytes();
    System.out.println(b.length);//13个字节,一个汉字三个字节:6+7
    try{
        FileOutputStream out = new FileOutputStream(file);
        out.write(b);//将b写入流中
        out.close();
        FileInputStream in = new FileInputStream(file);
        int n=0;
		//从流中读取数据的时候会改变b作为缓冲区数组的前两位
        while((n=in.read(b, 0, 2))!=-1){//从流中一次读取两个byte,只有一个时不会返回-1
            String str = new String(b, 0, 2);
            System.out.println(str);
        }
        in.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

写文件

FileWriter用来创建写文件,BufferWriter用来指定从缓冲区写入文件的对象。
filewriter

File 创建一个文件夹对象,指定要过滤文件的文件夹

FileAccept 实现了一个接口FilenameFilter,指定要过滤的文件的后缀,
FileAccept类的接口

File filename[]数组是所有符合后缀的文件对象

注意点:

  • out.write 之后不能直接写到文件内,要使用out.flush
  • 因为进行读写操作时, 数据先读取到缓存中, 再从缓存中读取写入文件. 因此从缓冲区读完数据后, 必须flush清空缓冲区, 同时将缓冲区的内容输出到文件夹内, 然后close关闭读写流.
  • https://blog.csdn.net/stzy00/article/details/39156819
@Test
public void readFile05() throws IOException {
    FileWriter toFile = new FileWriter("D:\\name1.txt");
    BufferedWriter out = new BufferedWriter(toFile);
    File dir = new File("D:\\图片");
    FileAccept accept = new FileAccept("jpg");
    File fileName[] = dir.listFiles(accept);
    for(int i=0; i<fileName.length; i++){
        System.out.println(fileName[i].getName() + fileName[i].length());
        out.write(i+" "+fileName[i].getName());
        out.newLine();
    }
    out.flush();
    out.close();
}
class FileAccept implements FilenameFilter{//过滤文件的名字
    String str=null;
    FileAccept(String s){
        str="."+s;//加上.,后缀
    }
    @Override
    public boolean accept(File dir, String name) {
        return name.endsWith(str);
    }
}

多种方法实现文件的读写:多种方法实现文件读写

Java并发编程

Thread类:Thread类

守护线程,setDaemon(true);

线程优先级,setPriority();

线程同步:同步代码块、同步锁、同步方法(考试主要考这个)。

同步方法:使用synchronized关键字,多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。同步机制可以使用synchronized关键字实现。**当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。**当synchronized方法执行完或发生异常时,会自动释放锁。

synchronized关键字:https://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html

Java多线程示例

package com.JavaCour;

import static java.lang.Thread.*;

public class test
{
    private int i = 10;
    private Object object = new Object();
    public static void main(String[] args) {
        test test = new test();
        Account account = new Account();
        MyThread1 myThread1 = test.new MyThread1(account);
        MyThread1 myThread11 = test.new MyThread1(account);
        myThread1.start();
        myThread11.start();
    }
    class MyThread extends Thread {
            @Override
            public void run() {
            synchronized (object) {
                i++;
                System.out.println("i:"+i);
                try {
                    System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
                    Thread.currentThread().sleep(1000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
                System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
                i++;
                System.out.println("i:"+i);
            }
        }
    }
    class MyThread1 extends Thread{
        Account account;
        public MyThread1(Account account){
            this.account=account;
        }
        @Override
        public void run(){
            try{
                sleep(100);// 要加上,不然执行太快了,看不出来交叉运行
            }catch(Exception e){
                e.printStackTrace();
            }
            account.display();
        }
    }
}

class Bank extends Thread{

}

class Account extends Thread{
    String accountNo;
    int money;

    /**
     * 不加synchronized输出的顺序是不一致的,加上会显示一个先一个后,不会交叉
     */
    public synchronized void display(){
        // 不加synchronized输出的顺序是不一致的,加上会显示一个先一个后,不会交叉
        for(int i=0; i<5; i++){
            System.out.println(Thread.currentThread().getName()+": "+i);
        }
    }
}
class Ticket implements Runnable{
    private int ticket=20;
    @Override
    public void run() {
        this.sell();
    }
    public synchronized void sell(){
        while(true){
            if(ticket<1){
                System.out.println("票已售完");
                System.exit(0);
            }
            System.out.println(Thread.currentThread().getName()+"卖出第"+(ticket--)+"张票");
            try{
                sleep(500);
                notifyAll();
                wait();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

wait、notify、notifyAll

https://www.liaoxuefeng.com/wiki/1252599548343744/1306580911915042

wait会将这个线程的锁释放掉,this锁。调用了wait之后,其他线程可以使用这个锁,和C++的条件变量类似

在这个教程里,一个添加任务队列的方法,一个是执行任务的方法,如果只是用synchronized关键字把这两个方法锁住,当需要getTask之前,这个线程可以检测任务队列是否为空,为空的话会一直阻塞这个线程;这个时候this就被锁住了,其他线程也不能获得,所以也不能添加任务,然后所有的线程都被锁住了。这个时候可以使用this.wait()方法将这个锁释放掉,这个问题就解决了。

调用wait方法之后,这个线程会处于等待的状态,可以使用notifyall(或notify)方法唤醒这个线程,继续获得任务执行。

注:wait、notify、notifyAll这三个方法都必须在被已经获得锁的方法里面使用,被notify、notifyAll唤醒的进程必须重新获得锁才可以继续执行

class TaskQueue {
    Queue<String> queue = new LinkedList<>();

    public synchronized void addTask(String s) {
        this.queue.add(s);
    }

    public synchronized String getTask() {
        while (queue.isEmpty()) {
            //this.wait();//优化版本
        }
        return queue.remove();
    }
}

买票的例子

package com.JavaCour;

import java.util.Scanner;

public class test implements Runnable{
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        test st=new test();
        String name;
        Scanner input=new Scanner(System.in);
        int imoney,flag;
        flag=1;
        while(flag==1) {
            System.out.println("input name:");
            name=input.next();
            System.out.println("input money");
            imoney=input.nextInt();
            Thread th=new Thread (st,name+"-"+imoney);
            th.start();
            System.out.println("1 continue; 0 end");
            flag=input.nextInt();
        }
    }
    int  x[]=new int [5];// 手里有的币种数量 5 10 20 50 100
    private int bk=0;//是否有钱 1/0
    test() {

    }
    //判断是否能找钱成功
    public boolean check(int money)
    {
        int a[] =new int [5];// 5 10 20 50 100
        System.arraycopy(x, 0, a, 0, 5);
        int needchange=money-5;
        if(needchange==0) return true;//不需要找钱
        else {
            int tp=0;//票子的金额
            for(int i=4;i>=0;i--) {//从最大的开始找钱,合乎实际情况
                if(a[i]>0) {//这个票种有剩余
                    if(i==4) tp=100;
                    else if(i==3) tp=50;
                    else if(i==2) tp=20;
                    else if(i==1) tp=10;
                    else if(i==0) tp=5;
                    while(needchange-tp>=0) {
                        needchange-=tp;//找钱
                        a[i]--;
                        if(a[i]<=0) break;//没有这个票种了
                    }
                    if(needchange==0) {//正好找完钱
                        System.arraycopy(a, 0, x, 0, 5);
                        return true;
                    }
                }
            }
            return false;
        }
    }

    @Override
    public void run() {
        // TODO 自动生成的方法存根
        String sst=Thread.currentThread().getName();// name+"-"+imoney
        String sstr[]=sst.split("-");
        int money=Integer.valueOf(sstr[1]);
        if(bk==0) x[1]=1;
        synchronized(this) {
            boolean fg=false;
            while(fg==false) {
                String st=Thread.currentThread().getName();// name+"-"+imoney
                String str[]=st.split("-");
                money=Integer.valueOf(str[1]);
                //System.out.println(money+"qqqqqq");
                if(check(money)==true) {//可以找完钱
                    System.out.println(Thread.currentThread().getName()+"买到票");
                    if(money==5) x[0]++;
                    else if(money==10) x[1]++;
                    else if(money==20) x[2]++;
                    else if(money==50) x[3]++;
                    else x[4]++;
                    for(int j=0;j<5;j++)
                        System.out.print("x["+j+"] " +x[j]+"  ");
                    System.out.println("");
                    super.notifyAll();//如果某一个顾客买票成功,则唤醒所有等待的顾客。
                    fg=true;
                    bk=1;// 卖完票银行就有钱了
                }
                else {
                    try {
                        System.out.println(Thread.currentThread().getName()+"没买到票");
                        for(int j=0;j<5;j++)
                            System.out.print("x["+j+"] " +x[j]+"  ");//输出bank的票种数量
                        System.out.println("");
                        super.wait();// 释放锁
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

交替按序输出1、2的例子:

package com.JavaCour;

public class ThreadTest{
    public static void main(String[] args) throws InterruptedException {
        ThreadTest2 t=new ThreadTest2();
        ThreadTest2 t2 = new ThreadTest2();//不能创建两个类,因为this锁,不一致
        for(int i=0; i<7; i++) {
            t.outA();
        }
        for(int i=0; i<7; i++) {
            t2.outB();
        }
//        new Thread(){
//            @Override
//            public void run() {
//                for(int i=0; i<7; i++) {
//                    try {
//                        t.outA();
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }.start();
//        new Thread(){
//            @Override
//            public void run() {
//                for(int i=0; i<7; i++) {
//                    try {
//                        t.outB();
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }.start();

    }
}
class ThreadTest2 extends Thread {
    @Override
    public void run() {

    }
    synchronized void outA() throws InterruptedException {
        this.notify();
        System.out.print(1);
        this.wait(1);
    }
    synchronized void outB() throws InterruptedException{
        this.notify();
        System.out.println(2);
        this.wait(1);
    }
}

//public class ThreadTest {
//    // 创建一个将被两个线程同时访问的共享对象
//    public static Object object = new Object();
//
//    // Thread0线程,执行wait()方法
//    static class Thread0 extends Thread {
//        @Override
//        public void run() {
//            synchronized (object) {
//                for(int i=1;i<=7;i++){
//                    object.notifyAll();
//                    System.out.println(Thread.currentThread().getName() + "---1");
//                    try {
//                        object.wait(1);}
//                    catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }
//    }
//    // Thread1线程,执行notify()方法
//    static class Thread1 extends Thread {
//
//        @Override
//        public void run() {
//            synchronized (object) {
//                for(int i=1;i<=7;i++){
//                    object.notifyAll();
//                    System.out.println(Thread.currentThread().getName() + "---2");
//                    try {
//                        object.wait(1);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        }
//    }
//
//    // 主线程
//    public static void main(String[] args) {
//        Thread0 thread0 = new Thread0();
//        Thread1 thread1 = new Thread1();
//        thread0.start();
//        thread1.start();
//        System.out.println("over!");
//    }
//}

JDBC

JDBC

package com.hzy;

import java.sql.*;

public class HelloJDBC {
    public static void main(String[] args) {

        String url = "jdbc:mysql://localhost:3306/hotel?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false";
        String drive = "com.mysql.cj.jdbc.Driver";
        String JDBC_USER = "root";
        String JDBC_PASSWORD = "123456";
        try (Connection conn = DriverManager.getConnection(url, JDBC_USER, JDBC_PASSWORD)) {// 先使用DriverManger.getConnection获取连接
            try (Statement stmt = conn.createStatement()) {// 使用Connection对象创建一个Statment对象,可能会有SQL注入,
                // PrepareStatement preStat=conn.prepareStatement();后面相同
                try (ResultSet rs = stmt.executeQuery("SELECT * FROM admin1")) {// 使用Statment的executeQuery传入Sql语句,返回结果用ResultSet来接受
                    while (rs.next()) {// 反复调用next方法来查询结果集
//                        long id = rs.getLong(1); // 注意:索引从1开始
//                        long grade = rs.getLong(2);
                        int id= rs.getInt(1);
                        String name = rs.getString(2);
                        int gender = rs.getInt(3);
                        System.out.println(id+name+gender);
                    }
                    conn.close();
                    stmt.close();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
//        try {
//            Class.forName(drive);
//            System.out.println("success");
//        }catch(Exception e){
//            e.printStackTrace();
//        }
    }
}

Array、ArrayList、数组、Arrays的简单区分

https://blog.csdn.net/weixin_44844089/article/details/103594587

javap的使用

https://www.cnblogs.com/baby123/p/10756614.html

Java的重载和重写

重载和重写的区分

重载发生在:重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

重写发生在:重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

split() 方法

split()方法

Declare: public String[] split(String regex, int limit);// limit是个数

Declare: public String[] split(String regex);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值