Java基础复习计划(三)

散碎知识点

  • Math.round() 方法进行四舍五入计算,实现是:Math.floor(a + 0.5f)

    floor : 意为地板,指向下取整,返回不大于它的最大整数

    ceil : 意为天花板,指向上取整,返回不小于它的最小整数

    round : 意为大约,表示“四舍五入”,而四舍五入是往大数方向入.

  • 关于方法区溢出:

    经常动态生成大量 Class 的应用中,Spring、hibernate 对类进行增强的时候使用 CGLib 类字节码技术 ,其他运行在 JVM 的动态语言;

    常见的还有大量 JSP 或动态产生 JSP 文件的应用(JSP 第一次运行时需要编译)

  • public Method[] getDeclaredMethods() 返回类或接口声明的所有方法,包括 public, protected, default (package) 访问和 private 方法的 Method 对象,但不包括继承的方法。当然也包括它所实现接口的方法。

    public Method[] getMethods() 返回类的所有 public 方法,包括其继承类的公用方法,当然也包括它所实现接口的方法。

  • 关于类加载器的简要分类:

    引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的。

    扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。

    系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。

    tomcat 为每个 App 创建一个 Loader,里面保存着此 WebApp 的 ClassLoader。需要加载 WebApp 下的类时,就取出 ClassLoader 来使用。

  • 方法内不能使用 static 修饰变量

线程

线程的五大状态:

  1. 新生(Born)
  2. 就绪(Runnable)
  3. 运行(Running)
  4. 消亡(Dead)
  5. 阻塞(Blocking)

创建线程的方式:

  1. extends Thread
  2. implements Runnable

控制线程的几种常见方法:

  • setPriority(int)

    设置线程的优先级,可选范围 1- 10,默认为 5,越大优先级越高;

    没什么意义,因为只是概率而已

  • static sleep(long)
  • join()

    当前线程邀请另一个线程优先执行,比如主线程里写 xx.join(); 意思就是主线程让 xx 线程执行完成后再执行,否则一直处于阻塞状态。

  • static yield()

    当前线程放弃持有的时间片,直接回到就绪,当然也有可能出现放弃时间片后又被 Cpu 选中的情况。

  • setName() + getName()
  • static activeCount()

    得到程序中所有活跃线程的总数,活跃线程:就绪 + 运行 + 阻塞;

    这个方法永远不可能返回 0,至少是 1.

  • static currentThread()

    得到当前线程对象,比如获得主线程的对象,在 run 方法调用的其他方法中使用;

    在 run 方法中没必要,直接 this 就是了。

  • setDaemon(true)

    设置成为守护进程,当程序中只剩下守护线程时会自动终结自己;

    Java 中著名的守护线程 GC,一般的特性:

  1. 通常是无限循环的
  2. 守护线程一般有极低的优先级
  3. 设置守护线程必须在 start 之前
  • interrupt()

    中断线程的阻塞状态,比如 sleep 时间还没到可以用 interrupt() 强制唤醒,但是会抛出一个异常。

线程中所有静态方法不关注谁调用的,而是关注出现在哪里,出现在哪里就是操作那个线程。

线程中所有涉及主动进入阻塞状态的方法都需要进行异常处理

关于锁

锁的出现就是为了解决并发错误,当多个线程共享同一个对象的时候,某一个线程未处理完成时 CPU 时间片就用尽了,然后就会出现并发错误。

然后就需要加锁来保证不会出现错误,通常有两种方案:

  • 使用 synchronized 关键字

    叫做互斥锁,或者互斥锁标记,它可以修饰方法或者代码块,用在代码块上要显式的声明锁,用在方法上默认是 this。

    还有就是 synchronized 特性本身不会被继承

  • java.util.concurrent.locks.ReentrantLock

    可翻译为可重用锁,JDK1.5 加入的,遵循了 OO 思想,有两个方法:lock() 和 unlock()

锁如果使用不当就会形成死锁,要解决死锁一般需要用到 Object 的三个方法:

  • wait()

    让当前线程放弃已持有的锁标记,并且进入调用方对象的等待池。

  • notify()

    唤醒调用方对象中等待池中的某个线程,是随机的。

  • notifyAll()

    唤醒调用方对象中等待池中的全部线程

这三个方法都必须在已经持有锁标记的前提下才能使用,所以它们都必须出现在synchronized(){当中}

锁池和等待池

利用每一个对象都有一个锁旗标,拥有这个旗标后才可以访问此对象的资源,当线程无法获取此对象的锁旗标时就会发生阻塞进入此对象的锁池,等待旗标的释放,当释放后所有的等待旗标的线程会被唤醒,进入就绪状态争夺旗标。

使用 wait 会进入等待池,遇到 synchrnized 会进入锁池;

进入等待池会释放当时持有的锁,而锁池不会;

锁池中,只要锁标记再度可用 线程自动离开,等待池 必须要 notify() 或者 notifyAll();

关于离开的去向:离开锁池前往就绪;离开等待池前往锁池(之前释放了锁,必须得重新获取锁,既然有人唤醒它,说明此时旗标肯定在别人手里)

关于线程池

关于这一块,之前在 这里 已经写过了,这次提提怎么使用就够了:

常规使用,用 ExecutorService 这个接口来写吧,以及线程的几种定义方式:

public class TestThreadPool{
  public static void main(String[] args) throws Exception{
    ExecutorService es = Executors.newFixedThreadPool(2);
    //             newCachedThreadPool();
    //             newSingleThreadExecutor()
    ThreadOne t1 = new ThreadOne();
    es.submit(t1);
    ThreadTwo t2 = new ThreadTwo();
    es.submit(t2);
    ThreadThree t3 = new ThreadThree();
    Future<String> f = es.submit(t3);
    System.out.println(f.get());
    //es.shutdown();
    es.shutdownNow();
  }
}
class ThreadThree implements Callable<String>{//JDK5.0
  @Override
  public String call() throws Exception{
    for(int i = 0;i<6666;i++){
      System.out.println("我是第三种方式");
    }
    return "End";
  }
}

class ThreadTwo implements Runnable{
  @Override
  public void run(){
    for(int i = 0;i<6666;i++){
      System.out.println("我是第二种方式");
    }
  }
}

class ThreadOne extends Thread{
  @Override
  public void run(){
    for(int i = 0;i<6666;i++){
      System.out.println("我是第一种方式");
    }
  }
}

线程池的创建官方推荐使用 Executors 来创建,常见的有 newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor;

第一种就是最简单的,也是最常用的,会事先维护几个线程,等任务来直接执行;

第二种是当有任务的时候再创建线程(避免浪费),任务执行完后会等待一分钟(默认),如果一分钟内没有新任务,那么此线程就会被终结;

第三种是同一时间只允许一个线程执行,其他的任务都排队等着,适合用在秒杀的情况。

shutdown 和 shutdownNow 的区别:

shutdown :不再接受新的任务,当线程池中的任务(包括等待中的和正在执行的)执行完毕后销毁线程池。

shutdownNow:试图停止所有正在执行的活动任务(一般情况正在执行的任务都会正常跑完的),暂停处理正在等待的任务,不再接受新任务,并返回等待执行的任务列表。

还有就是通过实现 Callable<> 的 call 方法来定义线程,这种方式定义的线程解决了其他方式无法实现的问题:

  • run() 被定义为 void 无法返回数据
  • run() 没有任何 throws 声明

这种方式定义的线程,只能通过线程池的方式来启动,并且 submit 的时候会返回一个 Future 对象,利用这个对象可以获得线程的返回值,就是调用其 get 方法,注意:当线程未执行完时,此方法一直是阻塞状态;当线程被意外终止那么 get 方法可能会一直卡在阻塞中(当然有重载可以指定等待的最大时间)。

IO

这就是通常我们所说的 IO 流了,流可分为三类:

  1. 方向分: 输入流 or 输出流
  2. 单位分: 字节流 or 字符流
  3. 功能分: 节点流 or 过滤流(包装流、处理流)

File对象

创建 File 对象的三种常见形式:

new File(String 完整路径);
new File(String 父目录,String 文件名);
new File(File 父目录对象,String 文件名);

然后介绍常用的几个方法:

  • static listRoots() : 得到当前计算机所有根目录
  • String[] list() : 动态的列出一个目录当中所有的文件名字
  • File[] listFiles() : 动态的列出一个目录当中所有的文件对象
  • exists() : 判断 File 对象指代的文件或者目录是否存在
  • isFile() : 判断 File 对象指代的是不是一个文件
  • isDirectory() : 判断 File 对象指代的是不是一个目录
  • length() : 得到文件的字节个数;只能对文件调用,对目录调用得到的没有意义
  • mkdirs() : 创建多层不存在的目录结构
  • getName() : 得到文件或者目录的名字
  • getParent() : 得到文件或者目录的父目录
  • getAbsolutePath() : 得到文件或者目录的绝对路径
  • setLastModified() : 设置文件的最后一次修改时间,设置的是时间戳
  • lastModified() : 得到文件的最后一次修改时间
  • delete() : 删除目录或者文件

    如果要删除的是一个目录 则必须保证目录是空的

  • renameTo() : 重命名文件或者目录

    例如:a.renameTo(c); a 代表源文件,必须存在;c 代表目标文件,必须不存在;

    其中 a 和 c 可以是不同的目录结构,从而实现剪切。

过滤器

使用 File 的 listFiles() 方法的时候可以传入一个文件过滤器(FileFilter),用来过滤指定的文件,这样能减轻接下来遍历的压力。

FileFilter 是个接口,并且它只定义了一个方法:boolean accept(File pathname) 比如:

class JavaFilter implements FileFilter{
  private JavaFilter(){}
  private static JavaFilter jf = new JavaFilter();
  public static JavaFilter getFilter(){
    return jf;
  }

  @Override
  public boolean accept(File f){
    return f.isFile() && f.getName().toLowerCase().endsWith(".java");
  }
}

class DirFilter implements FileFilter{
  private DirFilter(){}
  private static DirFilter df = new DirFilter();
  public static DirFilter getFilter(){
    return df;
  }

  @Override
  public boolean accept(File f){
    return f.isDirectory();
  }
}

// 使用 lambda
File[] files = file.listFiles(f -> f.isFile() && f.getName().endsWith(".java"));
File[] dirs = file.listFiles(f -> f.isDirectory());
if(files == null) return;

一个来过滤 Java 文件,一个来过滤目录,这里使用单例模式就比较适合了,另外,还可以直接使用 lambda 表达式,更加的爽

字节流

首先要认识的两个对象是:InputStream 和 OutputStream,他们分别是:所有字节输入流统一的父(抽象)类、所有字节输出流统一的父(抽象)类。

方法一览:

// 一次读一个字节,并返回这个字节
int read();
// 一次读一个数组,返回读取的长度
int read(byte[] data);
// 一次读一个数组,从 off 开始填充,填充 len 个
int read(byte[] data,int off,int len);

write(int data);
write(byte[] data);
write(byte[] data,int off,int len);

需要注意:一次读一个字节但是返回的是 int,这是为了确保返回值 -1 表示文件的结束,假设读到了一个字节是 -1,那么先会进行类型提升到 int,这里的提升是 &0xff 来确保前面补的是 0 而不是 1。

读取数组时,如果读到最后不足一个数组的大小,那么返回的 int 就不是 data.length,所以说并不是绝对的。



上面说的是顶级的抽象类,下面就来说说最常用的两个具体类:FileInputStream 和 FileOutputStream。

  • 它们作为节点流,构造方法可以指定连接 String 文件名 File 对象
  • 虽然贵为节点流,但是它们只能连接文件 不能连接目录
  • 节点输出流连接的文件即便不存在在,创建流的时候也会被自动创建出来,但是如果连接的目录结构都不存在 则直接异常【File 类还有个 mkdirs()】
  • 节点输出流连接的文件即便已经存在,在创建流的一刻 也会被新的空白文件直接替换。

    如果我们的需求是想要在最后追加内容,那么构造方法:new FileOutputStream("abc.txt",true);

  • FileInputStream 最常用的是 read(byte[] data);;FileOutputStream 最常用的却是 write(byte[],int,int)
  • FileInputStream 以 -1 作为读取结束的标识

下面看经典的复制文件的例子:

public class FileCopy{
  public static void main(String[] args){
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try{
      fis = new FileInputStream("1.mp3");
      fos = new FileOutputStream("2.mp3");
      // 2^10 = 1024 也就是字节 <<10 是 kb,再 <<10 是 mb
      byte[] data = new byte[5<<20];  // 5MB
      int len = 0;
      while((len = fis.read(data)) != -1){
        fos.write(data,0,len);
      }
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      try{
        fis.close();
      }catch(Exception e){
        e.printStackTrace();
      }finally{
        try{
          fos.close();
        }catch(Exception e){
          e.printStackTrace();
        }
      }
    }
  }
}

// 简写
public class FileCopy2{
    public static void main(String[] args){
        // JDK7+ 特性。
        try(FileInputStream fis = new FileInputStream("1.mp3");
            FileOutputStream fos = new FileOutputStream("3.mp3")){
            byte[] data = new byte[5<<20];
            int len;
            while((len = fis.read(data)) != -1){
                fos.write(data,0,len);
            }
        }catch(Exception e){e.printStackTrace();}
    }
}

设置缓冲大小使用位运算效率更高哦,只需要记住 x<<20 就是 xMB 大小的缓冲区。

JDK7 后有了特性,就不用在 finally 里写这么恶心的代码了。。。。

过滤流

之所以称它们为过滤流是因为他们接收的对象是 stream,并不能直接传 file 或者路径,对于字节流来说,有几个还算用的多的字节流过滤流:

BufferedInputStream、BufferedOutputStream、DataInputStream、DataOutputStream、ObjectInputStream、ObjectOutputStream。

经过过滤(包装)后,后面的操作只需要对这个过滤流操作就行了,因为是装饰(包装)模式,最后关流的时候只关过滤流就 OK 了。



前两个:

作为过滤流的它们是为了给原本的节点流添加缓冲空间,从而提高每次读写的吞吐量 进而提高效率。它们构造方法的第二个参数可以指定缓冲空间大小(默认只有8192字节,也就是 8k);一定记得及时清空缓冲空间 防止数据滞留缓冲区,其中有三种情况会刷新缓冲区:1、当缓存空间满了的时候自动刷新;2、当关闭流操作时会自动刷新;3、手动调用 flush。

这样,即使你调用 read 方法一个字节一个字节的读其实它会一次读指定的大小到缓冲区,然后一个个的给你;写也是,并不是一个个的写,而是写到缓冲区,满了以后一次性 flush 到硬盘。



中间两个:

是为了给原本的节点流添加读写基本数据类型的功能;DataInputStream 提供了一组方法 readXxxx();,DataOutputStream 提供一组方法 writeXxxx(); ,这时候不再以 -1 作为读取结束的标识了,而是如果已经到达文件结尾还继续读取,则直接出现 EOFException(End of File)。

public static void main(String[] args){
  try(DataOutputStream dos = new DataOutputStream(new FileOutputStream("t.data"))){
    dos.writeInt(4545);
  }catch(Exception e){e.printStackTrace();}

  try(DataInputStream dis = new DataInputStream(new FileInputStream("t.data"))){
    int x = dis.readInt();
    System.out.println(x);
  }catch(Exception e){e.printStackTrace();}
}


最后两个:

给原本的节点流添加读写对象的功能的,与上面类似,对应的方法就是 readObject();writeObject();

同样不以 -1 作为结束,而也会 EOFException。

要写出的对象必须先要序列化 (implements Serializable),如果要持久化的对象当中有其它引用类型的属性,那么也要进行序列化标识;但是如果某些属性无关紧要,不需要保存(那就相当于是 null 了),可以直接使用 transient 修饰。

如果要持久化的是一个使用了比较器的 TreeSet 或者 TreeMap,就连比较器的类型也要实现序列化接口。

字符流

和字节流一样,两大鼻祖:Read 和 Writer;接口中定义的方法也和字节流中的那三个对应,就不写了。

两个常用的具体类:FileReader 和 FileWriter,描述也不多说了,和上面 FileInputStream 和 FileOutputStream 一样一样的

过滤流

对于字符流来说,最常用的还是莫过于这里说的过滤流,因为对于字符操作,过滤流提供了更方便的方法。

BufferedReader 和 BufferedWriter:

通过对原有的字符流添加缓冲空间,使其可以支持一次读取一行(readLine),和一次写入一个字符串(write + newLine 换行)。其中 BufferReader 使用的非常频繁,必须要熟练的。

PrintStream 和 PrintWriter:

像是一对姐妹,他们的方法一致,不同的是一个输出字节,一个输出字符;PrintStream 我们最长见的就是打印语句中的 out,它就是 PrintStream 类型的,然后 PrintWriter 在 IO 操作中用的非常频繁,相比 BufferedWriter 它更加的好用。

既然说好用,那就来看看它的特点吧:

  • 既可以作为节点流,又可以作为过滤流;也就是可以直接往构造函数里扔文件对象、路径、节电流
  • 既可以连接字节流,又可以连接字符流;是的,构造函数里都可以扔,不需要转换流
  • 当做节点流的时候,构造方法第二个参数可以指定字符集
  • 当做过滤流的时候,构造方法第二个参数可以指定自动清空缓冲

    例如:new PrintWriter(new FileWriter("a.txt",true),true);

    第一个 true 是开启追加模式,第二个是自动刷新(flush)

  • 拥有 println() 方法,等价于 write() + newLine()


转换流(桥转换器):InputStreamReader 和 OutputStreamReader ,其中最常用的是 InputStreamReader,实际用法例如:

new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")))

而 OutputStreamReader 基本不怎么用,因为有 PrintWriter 啊,它可以字符流字节流通吃,也就是说内部会内置一个转换流,就是这个 OutputStreamReader ,所以让我们方便了。



再来补充个 RandomAccessFile 用来支持随机文件的读取和写入,通常可以用它来占空间,然后用流来对其进行写:

RandomAccessFile raf = new RandomAccessFile("d:\\abc.mp4","rw");
File d = new File("d:\\");
long free = d.getFreeSpace();//得到d盘的剩余空间
raf.setLength(free);
raf.close();

这只是个简单的使用,这里先 TODO

原码反码补码

对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值,原码是人脑最容易理解和计算的表示方式。

```

[+1]原 = 0000 0001

[-1]原 = 1000 0001

```

正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

```

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

```

正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

```

[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

```

那么为何要使用原码, 反码和补码?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域(可理解为不加符号位的二进制表示)的加减。

但是对于计算机,加减乘数已经是最基础的运算,要设计的尽量简单; 计算机辨别 "符号位" 显然会让计算机的基础电路设计变得十分复杂!

于是人们想出了将符号位也参与运算的方法; 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法, 首先来看原码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的;这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

发现用反码计算减法, 结果的真值部分是正确的.

而唯一的问题其实就出现在 "0" 这个特殊的数值上, 虽然人们理解上 +0 和 -0 是一样的,但是 0 带符号是没有任何意义的, 而且会有 [0000 0000]原 和 [1000 0000]原 两个编码表示 0.

于是补码的出现, 解决了 0 的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

这样 0 用 [0000 0000] 表示, 而以前出现问题的 -0 则不存在了;而且可以用 [1000 0000] 表示 -128:

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补

-1-127 的结果应该是 -128, 在用补码运算的结果中 [1000 0000]补 就是 -128, 但是注意因为实际上是使用以前的 -0 的补码来表示 -128, 所以 -128 并没有原码和反码表示(所以可以多表示一个最低数).(对 -128 的补码表示 [1000 0000]补 算出来的原码是 [0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了 0 的符号以及存在两个编码的问题, 而且还能够多表示一个最低数; 这就是为什么 8 位二进制, 使用原码或反码表示的范围为 [-127, +127], 而使用补码表示的范围为 [-128, 127].

因为机器使用补码, 所以对于编程中常用到的 32 位 int 类型,可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

出自:https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

其他

查找一个字符串出现多少次?

可以使用 (str + "l").split("abc").length - 1 ,源字符串加任意一个字符防止被 split 的字符在最后会导致少一个,然后它的 length - 1 就是个数。

原文地址:https://www.cnblogs.com/bfchengnuo/p/9193007.html

时间: 2024-10-30 20:55:17

Java基础复习计划(三)的相关文章

Java基础复习计划(二)

散碎知识点 通过 HttpServletRequest. getParameter() 获取的参数编码格式由浏览器决定. 浏览器根据 html 中指定的编码格式进行编码,tomcat 根据指定的格式进行解码,tomcat 默认解码是 ISO-8859-1. get 请求使用 new String(username.getBytes("ISO-8859-1"), "UTF-8"); 解决乱码: post 请求使用 request.setCharacterEncodin

java基础复习(三)

一.运算符 1.算术运算符 1) 加法(+) 加法   正号  字符串拼接 2) 减法(-) 减法 负号 3) 乘法 (*) 乘法 4) 除法(/) 除法 整数(小数)相除的例子 10/3 =3:  10.0/3=3.33333-   0/0   0.0/0.0 结果是NaN ,任何的NaN都不等于自己(面试题) 1.0/0.0 Infinity,表示无穷大 5) 取模(%) 2.自增自减 ++(自增)     --(自减)  自增自减只能够用于 变量,不能用于常量  自增自减运算的优先级  比

Java基础复习---第三章

第三章 面向对象 面向对象更加强调运用人类在日常的是为逻辑中采用的思想方法与原则 抽象.分类.继承.聚合.多态 面向对象与面向过程 ? 面向过程:强调的是功能行为 ? 面向过程:将功能封装进对象,强调具备了功能的对象 面向对象三大特征 ? 封装.继承.多态 OOP思想概述 类 :对现实世界事物的抽象定义 对象:类的实体(实例) ? ? ps. 类就像汽车设计图 对象就像实际的汽车 ? 类(class)和对象(object)是面向对象的核心概念.类是对现实世界事物的描述,类是抽象.概念上的定义.

Java基础知识的三十个经典问答

Java基础知识的三十个经典问答 1.面向对象的特点 抽象: 抽象是或略一个主题中与当前目标的无关的因素,一边充分考虑有关的内容.抽象并不能解决目标中所有的问题,只能选择其中的一部分,忽略其他的部分.抽象包含两个方面:一是过程抽象:一是数据抽象. 继承 继承是一种联接类的层次模型,允许和鼓励类的重用,提供了一种明确的共性的方法.对象的一个新类可以从现有的类中派生,这叫做类的继承.心累继承了原始类 的特性,新类称为原始类的派生类或者是子类,原始类称为新类的基类或者父类.子类可以从父类那里继承父类的

Java基础复习笔记系列 四

Java基础复习笔记系列之 数组 1.数组初步介绍? Java中的数组是引用类型,不可以直接分配在栈上.不同于C(在Java中,除了基础数据类型外,所有的类型都是引用类型.) Java中的数组在申明时,不能指定其长度.不同于C 数组的小标可以是整型常量或整型表达式. .length方法是显示数组的长度:数组.length;String.length();一个是属性,一个是方法.注意区分. 2.数组的内存分析? Array a[]; a = new Integer(15); /*这个a在栈中,在堆

Java基础复习㈥ 内存分配

1.方法区 类的全限定名.直接超类的全限定名.该类是类或者接口.访问修饰符.直接超接口全限定名: 运行时常量池.字段.方法.静态变量.到类装载器的引用.到类class的引用 2.栈内存 局部变量区.操作数栈.帧数据区 3.堆内存 存放由new创建的对象和数组 *栈内存和堆内存 栈存取速度比堆快,仅次于寄存器,栈数据可以共享.栈中主要存放一些基本类型的变量和对象句柄 4.本地方法栈内存 5.String ① String str1 = "abc"; String str2 = "

Java基础复习笔记系列 五 常用类

Java基础复习笔记系列之 常用类 1.String类介绍. 首先看类所属的包:java.lang.String类. 再看它的构造方法: 2. String s1 = “hello”: String s2 = “hello”:结论:s1 == s2. 字符串常量放在data区. 3. String s3 = new String("hello"); String s4 = new String("hello");结论:s3 != s4.但s3.equals(s4).

Java基础复习笔记系列 七 IO操作

Java基础复习笔记系列之 IO操作 1. 2.

Java基础复习笔记系列 十 GUI

Java基础复习笔记系列之 GUI 1. 2.