站点图标 久久日记本

Java拾遗

写过一些react-native的小软件,一个发现,性能问题太大,各种实现起来比较麻烦,依赖第三方库严重,而且每次升级底层都是痛苦。

想了想,做了个艰难的决定,索性换用Android StudioJava感觉兼容性会更好一些吧。

接下来的笔记会记录一些Java的语法,因为做过C#,看起来比较轻松。

不过它是仅仅是为了更好的理解Android开发中的Java代码而记录的。

1.定义

定义包名称:

package name;

打包:

javac -d . *.java

引用包之后 new

com.pk.Ct c = new Ct();
c.function();

方法或者·属性必须是public`才允许被调用

同一个包中的不同java文件中方法属性可以互相访问

public 自由访问
private 只能在本类中访问
default 同一个包里面可以自由访问
protect 

2.导入包

导入包:

一个简单的demo:

package com.pk;

public class Ct {

    public String name;

    public Ct(String name) {
        this.name = name;
    }

    public void Say() {
        System.out.println("pk.Ct name: " +this.name);
    }
}
package net.pk;

import com.pk.Ct;

class Test {
    public static void main(String[] args) {
        String name="Test function";
        // 未导入
        // com.pk.Ct c = new Ct(name);
        // 导入
        Ct c = new Ct(name);
        c.Say();
    }
}

类似C#引入类库

3.包继承

只有类是公共的包才能被其它包引用,

如果子类和父类不在同一个包当中,则子类无法继承父类中default权限的成员变量和成员函数

如果子类和父类不在同一个包当中,子类可以集成到父类当中的default权限的成员变量和成员函数,但是由于权限不够,无法使用

protected权限首先拥有和defult一样的权限,但是该权限只能修饰成员变量和成员函数,即使子类和父类在不同的包当中

package com.testjava;
  |
  |
People.java

package net.testjava;
  |
  |
Student.java 
Test.java

People.java

package com.testjava;

public class People {
  public String name; // public
  protected int age; // protected

  void Say() {
    System.out.println("say people");
  }

  void Sleep() {
    System.out.println("sleep people");
  }

}

Student.java

package net.testjava;

import com.testjava.People;

class Student extends People {

  void Introduce() {
    System.out.println("my name is " + name + ", my age is " + age);
  }
}

Test.java

package net.testjava;

import com .testjava.People;

class Test{
  public static void main(String args []){
    People p=new People();
    p.name="Test"; // public
    p.age=20; // protected
  }
}
C:\study\packageextend>javac -d . People.java
C:\study\packageextend>javac -d . Student.java
C:\study\packageextend>javac -d . Test.java
Test.java:9: error: age has protected access in People
    p.age=20; // protected  可以夸包使用,但是仅限父类子类;不同包的类只能访问public声明的成员变量或者函数
     ^
1 error

4.接口

接口的方法都会是public,不管前面加不加public

实现接口要用implements关键字,实现继承要用extends

             --Bird.java--Chicken.java
  Duck.java-|
             --Animal.java

一个类可以继承多个接口

一个接口可以继承多个接口

5.多接口继承与方法覆写

A.java

interface A {
  void Afun();
}

B.java

interface B {
  void Bfun();
}

C.java

// C继承A,B接口
// 如果用类来实现C,则需要覆写这A,B,C的三个方法
interface C extends A, B {
  public void funC();
}

6.接口的应用:工厂模式

Printer
|
| PrinterFactory A,B 打印机不需要关心子类,对于维护PrinterFactory来说,只需要维护工厂即可
|
APrinter
BPrinter

接口类 Printer.java

public interface Printer {
  public void open();

  public void print();

  public void close();
}

APriter.java

class APriter implements Printer {
  public void open() {
    System.out.println("A open");
  }

  public void print() {
    System.out.println("A print");
  }

  public void close() {
    System.out.println("A close");
  }

}

BPriter.java

class BPriter implements Printer {
  public void open() {
    System.out.println("B open");
  }

  public void print() {
    System.out.println("B print");
  }

  public void close() {
    System.out.println("B close");
  }

  private void sendemail() {
    System.out.println("B send email");
  }
}

Test.java

class Test {
  public static void main(String[] args) {
    // 根据用户的选择,生产相应的打印机对象
    // 并且向上转型位Printer类型
    // Printer getPrinter(int flag)
    // option 1
    // Printer printer =null;
    // int flag=1;
    // if(flag==0){
    //   printer = new APriter();
    // }else if (flag==1){
    //   printer = new BPriter();
    // }
    // printer.open();
    // printer.print();
    // printer.close();
  }
}
> C:\study\java4andcode\factory>javac -d . *.java

> C:\study\java4andcode\factory>java Test
A open
A print
A close

> C:\study\java4andcode\factory>javac -d . *.java

> C:\study\java4andcode\factory>java Test
B open
B print
B close

工厂模式思路很简单,可以认为是把生成对象的代码 (使用 new 来调用构造函数函数的代码 ) 封装到工厂方法中

添加一个工厂模式

class PrinterFactory {
  public static Printer getPrinter(int flag) {
    Printer printer =null;
    if(flag==0){
      printer = new APriter();
    }else if (flag==1){
      printer = new BPriter();
    }else if(flag==2){
      printer = new XXXPrinter();
    }
    return printer;
  }
}

这样在主函数 Test.java 调用就可以调用工厂

class Test {
  public static void main(String[] args) {
    // option 2 :factory
    int flag=2;
    Printer printer = PrinterFactory.getPrinter(flag);
    printer.open();
    printer.print();
    printer.close();
  }
}

7.java中的异常

C#一样,使用try...catch...finally 结构捕获异常

uncheck exception 和 Check exception

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

    // uncheck exception
    int i = 1/0;

    // Check exception
    Thread.sleep(1000);
  }
}

try...catch...finally 的使用

class Test {
  public static void main(String[] args) {
    // uncheck exception
    try {
      int i = 1/0;
    } catch (Exception e) {
      //TODO: handle exception
      e.printStackTrace();
    } finally {
      System.out.println('finally')
    }

    // Check exception
    // try {
    //   Thread.sleep(1000);
    // } catch (Exception e) {
    //   //TODO: handle exception
    //   e.printStackTrace();
    // }
  }
}
C:\trycatch>javac Test.java

C:\trycatch>java Test
java.lang.ArithmeticException: / by zero
        at Test.main(Test.java:5)

自定义异常

User.java

class User {
  public String name;
  private int age;

  public void setAge(int age) {
    if(age < 0){
      // 自定义异常
      RuntimeException e = new RuntimeException("age can't be less than 0");
      throw e; // 抛出异常
    }
    this.age = age;
  }
}

SelfTest.java

class SelfTest{
  public static void main(String[] args) {
    User user = new User();
    user.setAge(-20);
  }
}
C:\study\java4andcode\trycatch>javac User.java

C:\study\java4andcode\trycatch>javac SelfTest.java

C:\study\java4andcode\trycatch>java SelfTest
Exception in thread "main" java.lang.RuntimeException: age can't be less than 0
        at User.setAge(User.java:8)
        at SelfTest.main(SelfTest.java:4)

C:\study\java4andcode\trycatch>

如果函数可能产生check expection异常,用Exception定义并在函数后声明可能产生的异常throws Exception(当声明后,该函数没有责任处理异常,需要由调用它的函数处理异常), 并在调用它的函数中用try...catch捕捉异常

User.java

class User {
  public String name;
  private int age;

  public void setAge(int age) throws Exception {
    if(age < 0){
      // 自定义异常
      // RuntimeException e = new RuntimeException("age can't be less than 0");
      Exception e = new Exception("age can't be less than 0"); // 抛出异常
      throw e; // 抛出异常
    }
    this.age = age;
  }
}

SelfTest.java

class SelfTest{
  public static void main(String[] args) {
    try {
      User user = new User();
      user.setAge(-20);
    } catch (Exception e) {
      //TODO: handle exception
      System.out.println(e);
    }

  }
}

thorw 抛出异常
throws 声明函数抛出异常,该函数不对异常进行处理,只在调用它的函数进行处理异常

8.java当中的IO

InputStream -> int read
OutputStream ->

Test.java

import java.io.FileOutputStream;

// 1.引入包
import java.io.*;
 class Test {
  public static void main(String[] args) {
    // 2.声明输入流引用
    FileInputStream fis= null;
    // 声明输出流的引用
    FileOutputStream fos=null;
    try {
      // 3.生成代表输入流的对象
      fis=new FileInputStream("./from.txt");
      // 生成代表输出流的对象
      fos=new FileOutputStream("./to.txt");
      // 4.生成一个字节数组
      byte [] buffer = new byte[100];
      // 5.调用输入流对象的read方法,读取
      // 返回值是int类型
      int temp = fis.read(buffer,0,buffer.length);
      // for (int i = 0; i < buffer.length; i++) {
      //   System.out.println(buffer[i]);
      // }
      fos.write(buffer,0,temp);

      // 调用一个String独享的trim方法将会去掉字符串首位空格和空字符
      String str=new String(buffer);
      System.out.println(str.trim());
    } catch (Exception e) {
      //TODO: handle exception
    }
  }
}
C:\study\java4andcode\io>javac -encoding utf-8 Test.java

C:\study\java4andcode\io>java Test
0123456789

数据量大的时候需要分段读取:

import java.io.FileInputStream;
import java.io.FileOutputStream;

// Test read large txt
// read a txt file by part
class TestL {
  public static void main(String[] args) {
    FileInputStream fis =null;
    FileOutputStream fos=null;
    try {
      fis = new FileInputStream("./news.txt");
      fos = new FileOutputStream("./to.txt");
      // 小写的byte
      // 每次读取1024个字节
      byte [] buffer=new byte[1024];
      // for (int i = 0; i < max; i++) {
      //   int temp=fis.read(buffer,0,buffer);
      //   if(temp==-1){
      //     break;
      //   }
      // } 
      while(true){
        int temp = fis.read(buffer,0,buffer.length);
        if(temp==-1){
          break;
        }
        fos.write(buffer,0,temp);
      }

    } catch (Exception e) {
      //TODO: handle exception
    } finally{
      // TestL.java:34: error: unreported exception IOException; must be caught or declared to be thrown
      // fis.close();
      //          ^
      // TestL.java:35: error: unreported exception IOException; must be caught or declared to be thrown
      try {
        fos.close();
        fis.close();
      } catch (Exception e) {
        //TODO: handle exception
      }

    }
  }
}
C:\study\java4andcode\io>javac -encoding utf-8 TestL.java

C:\study\java4andcode\io>java TestL

字节流:读写文件时,以字符为基础
字节输入流:Reader <-- FileReader
int read(char [] c, int off, int len)
字节输出流:Writer <-- FileWriter
void write(char [] c, int off, int len)

char[] buffer = new char[100];
int temp = fr.read(buffer, 0, buffer.length);
// for (int i = 0; i < buffer.length; i++) {
// System.out.println(buffer[i]);
// }
fw.write(buffer, 0, temp);

一行一行的读取

装饰者模式

9.内部类与匿名函数

class A {
  class B{
  }
}

编译后会生成两个文件,一个是A.class,一个是A$B.class

匿名函数


B b = new B(); // b.fun(a); // 匿名函数 b.fun(new A(){ public void dosomething(){ System.out.println('匿名函数'); } });

10.线程

继承Thread,重写run方法

// 继承的方式
class T1 extends Thread {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
// 实现接口的方式
class T2 implements Runnable {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}
class Test {
    public static void main(String[] args) {
        // 生成线程类的对象
        T1 t1=new T1();
        // 启动线程
        t1.start(); //start 方法来自Thread
        // t1.run(); //这种是调用方法,不是执行线程
    }
}

中断线程

Thread.sleep()
Thread.yield()

设置线程的优先级

getPriority()
setPriority()
        // 2 通过实现接口来实现多线程 Runnable
        //  生成T1的接口实现类的对象
        T2 t2 = new T2();
        // 生成一个Thread对象
        // 传递给该Thread对象
        Thread t = new Thread(t2);
        // 设置优先级
        t.setPriority(Thread.MAX_PRIORITY);
        // 通知Thread对象,执行start方法
        t.start();
        // 获取当前优先级
        System.out.println(t.getPriority());

线程的优先级最大是10,最小是1,可以使用Thread提供的静态常量来设置线程的优先级

// 设置线程名称
t.setName("线程1");
// 获取线程名称
t.getName();
// Thread.currentThread() 当前代码正在哪个线程中运行,返回线程对象
Thread.currentThread().getName(); //获取线程名称
// 线程让步
Thread.yield();
// 同步代码块
// 同步锁,在一个线程执行某个代码块的时候,另一个线程不会插入其中影响
synchronized (this) {
    // do some thing
}

11.编译问题

UTF-8编码的文件, 文件中有中文,可能在编译中报错String literal is not properly closed by a double-quote Java(1610612995)

改成UTF-8编码即可

C:\study\java4andcode\io>javac -encoding utf-8 TestL.java

于 2018-12-07 至 2019-01-04

12.参考资料:

源代码

Mars 老师的视频

Thread中yield方法

退出移动版