精华内容
下载资源
问答
  • Java 3DMenu 界面源码 5个目标文件 内容索引:Java源码,窗体界面,3DMenu Java 3DMenu 界面源码,有人说用到游戏不错,其实平时我信编写Java应用程序时候也能用到吧,一定非要局限于游戏吧,RES、SRC资源都有,都...
  • 26、(多选题)下列哪些选项属于Java技术体系() A.Java Me B.Java Se C.Java EE D.Java Card 【正确答案】A,B,C,D 【答案解析】Java Card、Java Me、Java Se、Java EE都属于Java技术体系

    26、(多选题)下列哪些选项属于Java技术体系()
    A.Java Me
    B.Java Se
    C.Java EE
    D.Java Card
    【正确答案】A,B,C,D
    【答案解析】Java Card、Java Me、Java Se、Java EE都属于Java技术体系

    展开全文
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
     Java 3DMenu 界面源码,有人说用到游戏不错,其实平时我信编写Java应用程序时候也能用到吧,一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...
  • Java多线程详解(一)Java多线程入门

    千次阅读 多人点赞 2019-11-27 20:18:20
    最近听很多面试的小伙伴说,网上往往是一篇一篇的Java多线程的文章,除了书籍没有什么学习多线程的一系列文章。但是仅仅凭借一两篇文章很难对多线程有系统的学习,而且面试的时候多线程这方面的知识往往也是考察的...

    最近听很多面试的小伙伴说,网上往往是一篇一篇的Java多线程的文章,除了书籍没有什么学习多线程的一系列文章。但是仅仅凭借一两篇文章很难对多线程有系统的学习,而且面试的时候多线程这方面的知识往往也是考察的重点,所以考虑之下决定写一系列关于Java多线程的文章。文章参考了高老师的《Java多线程编程核心技术》。力争使用最短的篇幅把Java多线程的知识作以系统的讲述。

    本节思维导图:

    思维导图源文件+思维导图软件关注微信公众号:“Java团长”回复关键字:“Java多线程”即可免费领取。

     

    一 进程和多线程简介

    1.1 相关概念

    何为线程?

    线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程

    何为进程?

    进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。

    线程和进程有何不同?

    线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。

    1.2 多线程

    何为多线程?

    多线程就是几乎同时执行多个线程(一个处理器在某一个时间点上永远都只能是一个线程!即使这个处理器是多核的,除非有多个处理器才能实现多个线程同时运行。)。几乎同时是因为实际上多线程程序中的多个线程实际上是一个线程执行一会然后其他的线程再执行,并不是很多书籍所谓的同时执行。

    为什么多线程是必要的?

    1. 使用线程可以把占据长时间的程序中的任务放到后台去处理
    2. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
    3. 程序的运行速度可能加快

    二 使用多线程

    2.1继承Thread类

    MyThread.java

    public class MyThread extends Thread {
    	@Override
    	public void run() {
    		super.run();
    		System.out.println("MyThread");
    	}
    }

    Run.java

    public class Run {
    
    	public static void main(String[] args) {
    		MyThread mythread = new MyThread();
    		mythread.start();
    		System.out.println("运行结束");
    	}
    
    }

    运行结果:

    结果

    从上面的运行结果可以看出:线程是一个子任务,CPU以不确定的方式,或者说是以随机的时间来调用线程中的run方法

     

    2.2实现Runnable接口

    推荐实现Runnable接口方式开发多线程,因为Java单继承但是可以实现多个接口

    MyRunnable.java

    public class MyRunnable implements Runnable {
    	@Override
    	public void run() {
    		System.out.println("MyRunnable");
    	}
    }

    Run.java

    public class Run {
    
    	public static void main(String[] args) {
    		Runnable runnable=new MyRunnable();
    		Thread thread=new Thread(runnable);
    		thread.start();
    		System.out.println("运行结束!");
    	}
    
    }

    运行结果:

    运行结果

     

    三 实例变量和线程安全

    定义线程类中的实例变量针对其他线程可以有共享和不共享之分

    3.1 不共享数据的情况

    MyThread.java

    public class MyThread extends Thread {
    
    	private int count = 5;
    
    	public MyThread(String name) {
    		super();
    		this.setName(name);
    	}
    
    	@Override
    	public void run() {
    		super.run();
    		while (count > 0) {
    			count--;
    			System.out.println("由 " + MyThread.currentThread().getName()
    					+ " 计算,count=" + count);
    		}
    	}
    }

    Run.java

    public class Run {
    	public static void main(String[] args) {
    		MyThread a = new MyThread("A");
    		MyThread b = new MyThread("B");
    		MyThread c = new MyThread("C");
    		a.start();
    		b.start();
    		c.start();
    	}
    }

    运行结果:

    运行结果

    可以看出每个线程都有一个属于自己的实例变量count,它们之间互不影响。我们再来看看另一种情况。

     

    3.2 共享数据的情况

    MyThread.java

    public class MyThread extends Thread {
    
    	private int count = 5;
    
    	@Override
    	 public void run() {
    		super.run();
    		count--;
    		System.out.println("由 " + MyThread.currentThread().getName() + " 计算,count=" + count);
    	}
    }

    Run.java

    public class Run {
    	public static void main(String[] args) {
    		
    		MyThread mythread=new MyThread();
            //下列线程都是通过mythread对象创建的
    		Thread a=new Thread(mythread,"A");
    		Thread b=new Thread(mythread,"B");
    		Thread c=new Thread(mythread,"C");
    		Thread d=new Thread(mythread,"D");
    		Thread e=new Thread(mythread,"E");
    		a.start();
    		b.start();
    		c.start();
    		d.start();
    		e.start();
    	}
    }

    运行结果:

    运行结果

    可以看出这里已经出现了错误,我们想要的是依次递减的结果。为什么呢??

    因为在大多数jvm中,count--的操作分为如下下三步:

    1. 取得原有count值
    2. 计算i -1
    3. 对i进行赋值

    所以多个线程同时访问时出现问题就是难以避免的了。

    那么有没有什么解决办法呢?

    答案是:当然有,而且很简单。

    在run方法前加上synchronized关键字即可得到正确答案

    加上关键字后的运行结果:

    加上关键字后的运行结果

    四 一些常用方法

    4.1 currentThread()

    返回对当前正在执行的线程对象的引用。

    4.2 getId()

    返回此线程的标识符

    4.3 getName()

    返回此线程的名称

    4.4 getPriority()

    返回此线程的优先级

    4.5 isAlive()

    测试这个线程是否还处于活动状态。

    什么是活动状态呢?

    活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备运行的状态。

    4.6 sleep(long millis)

    使当前正在执行的线程以指定的毫秒数“休眠”(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。

    4.7 interrupt()

    中断这个线程。

    4.8 interrupted() 和isInterrupted()

    interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能

    isInterrupted(): 测试线程Thread对相关是否已经是中断状态,但部清楚状态标志

    4.9 setName(String name)

    将此线程的名称更改为等于参数 name 。

    4.10 isDaemon()

    测试这个线程是否是守护线程。

    4.11 setDaemon(boolean on)

    将此线程标记为 daemon线程或用户线程。

    4.12 join()

    在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了

    join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行

    4.13 yield()

    yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。注意:放弃的时间不确定,可能一会就会重新获得CPU时间片。

    4.14 setPriority(int newPriority)

    更改此线程的优先级

    五 如何停止一个线程呢?

    stop(),suspend(),resume()(仅用于与suspend()一起使用)这些方法已被弃用,所以我这里不予讲解。

     

    5.1 使用interrupt()方法

    我们上面提到了interrupt()方法,先来试一下interrupt()方法能不能停止线程 MyThread.java

    public class MyThread extends Thread {
    	@Override
    	public void run() {
    		super.run();
    		for (int i = 0; i < 5000000; i++) {
    			System.out.println("i=" + (i + 1));
    		}
    	}
    }

    Run.java

    public class Run {
    
    	public static void main(String[] args) {
    		try {
    			MyThread thread = new MyThread();
    			thread.start();
    			Thread.sleep(2000);
    			thread.interrupt();
    		} catch (InterruptedException e) {
    			System.out.println("main catch");
    			e.printStackTrace();
    		}
    	}
    
    }

    运行上诉代码你会发现,线程并不会终止

    针对上面代码的一个改进:

    interrupted()方法判断线程是否停止,如果是停止状态则break

    MyThread.java

    public class MyThread extends Thread {
    	@Override
    	public void run() {
    		super.run();
    		for (int i = 0; i < 500000; i++) {
    			if (this.interrupted()) {
    				System.out.println("已经是停止状态了!我要退出了!");
    				break;
    			}
    			System.out.println("i=" + (i + 1));
    		}
    		System.out.println("看到这句话说明线程并未终止------");
    	}
    }

    Run.java

    public class Run {
    
    	public static void main(String[] args) {
    		try {
    			MyThread thread = new MyThread();
    			thread.start();
    			Thread.sleep(2000);
    			thread.interrupt();
    		} catch (InterruptedException e) {
    			System.out.println("main catch");
    			e.printStackTrace();
    		}
    		System.out.println("end!");
    	}
    
    }

    运行结果:

    运行结果

    for循环虽然停止执行了,但是for循环下面的语句还是会执行,说明线程并未被停止。

     

    5.2 使用return停止线程

    MyThread.java

    public class MyThread extends Thread {
    
    	@Override
    	public void run() {
    			while (true) {
    				if (this.isInterrupted()) {
    					System.out.println("ֹͣ停止了!");
    					return;
    				}
    				System.out.println("timer=" + System.currentTimeMillis());
    			}
    	}
    
    }

    Run.java

    public class Run {
    
    	public static void main(String[] args) throws InterruptedException {
    		MyThread t=new MyThread();
    		t.start();
    		Thread.sleep(2000);
    		t.interrupt();
    	}
    
    }

    运行结果:

    运行结果

    当然还有其他停止线程的方法,后面再做介绍。

    六 线程的优先级

    每个线程都具有各自的优先级,线程的优先级可以在程序中表明该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定首先使哪个线程进入运行状态。但这个并不意味着低 优先级的线程得不到运行,而只是它运行的几率比较小,如垃圾回收机制线程的优先级就比较低。所以很多垃圾得不到及时的回收处理。

    线程优先级具有继承特性比如A线程启动B线程,则B线程的优先级和A是一样的。

    线程优先级具有随机性也就是说线程优先级高的不一定每一次都先执行完。

    Thread类中包含的成员变量代表了线程的某些优先级。如Thread.MIN_PRIORITY(常数1)Thread.NORM_PRIORITY(常数5), Thread.MAX_PRIORITY(常数10)。其中每个线程的优先级都在Thread.MIN_PRIORITY(常数1)Thread.MAX_PRIORITY(常数10) 之间,在默认情况下优先级都是Thread.NORM_PRIORITY(常数5)

    学过操作系统这门课程的话,我们可以发现多线程优先级或多或少借鉴了操作系统对进程的管理。

    线程优先级具有继承特性测试代码:

    MyThread1.java:

    public class MyThread1 extends Thread {
    	@Override
    	public void run() {
    		System.out.println("MyThread1 run priority=" + this.getPriority());
    		MyThread2 thread2 = new MyThread2();
    		thread2.start();
    	}
    }

    MyThread2.java:

    public class MyThread2 extends Thread {
    	@Override
    	public void run() {
    		System.out.println("MyThread2 run priority=" + this.getPriority());
    	}
    }

    Run.java:

    public class Run {
    	public static void main(String[] args) {
    		System.out.println("main thread begin priority="
    				+ Thread.currentThread().getPriority());
    		Thread.currentThread().setPriority(6);
    		System.out.println("main thread end   priority="
    				+ Thread.currentThread().getPriority());
    		MyThread1 thread1 = new MyThread1();
    		thread1.start();
    	}
    }

    运行结果:

    运行结果

     

    七 Java多线程分类

    7.1 多线程分类

    用户线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程

    守护线程:运行在后台,为其他前台线程服务.也可以说守护线程是JVM中非守护线程的 “佣人”

    特点:一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作

    应用:数据库连接池中的检测线程,JVM虚拟机启动后的检测线程

    最常见的守护线程:垃圾回收线程

    7.2 如何设置守护线程?

    可以通过调用Thead类的setDaemon(true)方法设置当前的线程为守护线程

    注意事项:

    1.  setDaemon(true)必须在start()方法前执行,否则会抛出IllegalThreadStateException异常
    2. 在守护线程中产生的新线程也是守护线程
    3. 不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑

    MyThread.java:

    public class MyThread extends Thread {
    	private int i = 0;
    
    	@Override
    	public void run() {
    		try {
    			while (true) {
    				i++;
    				System.out.println("i=" + (i));
    				Thread.sleep(100);
    			}
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }

    Run.java:

    public class Run {
    	public static void main(String[] args) {
    		try {
    			MyThread thread = new MyThread();
    			thread.setDaemon(true);
    			thread.start();
    			Thread.sleep(5000);
    			System.out.println("我离开thread对象也不再打印了,也就是停止了!");
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }

    运行结果:

    守护线程

     

    如果你觉得博主的文章不错,欢迎转发点赞。

    参考:

    展开全文
  • 主要介绍了java IO流——四大抽象类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Java的常用输入输出语句

    万次阅读 多人点赞 2018-04-14 19:03:38
    作为一种语言体系,java中主要按照流(stream)的模式来实现。其中数据的流向是按照计算机的方向确定的,流入计算机的数据流叫做输入流(inputStream),由计算机发出的数据流叫做输出流(outputStream)。Java语言体系中...

    一、概述

       输入输出可以说是计算机的基本功能。作为一种语言体系,java中主要按照(stream)的模式来实现。其中数据的流向是按照计算机的方向确定的,流入计算机的数据流叫做输入流(inputStream),由计算机发出的数据流叫做输出流(outputStream)

    Java语言体系中,对数据流的主要操作都封装在java.io包中,通过java.io包中的类可以实现计算机对数据的输入、输出操作。在编写输入、输出操作代码时,需要用import语句将java.io包导入到应用程序所在的类中,才可以使用java.io中的类和接口。大笑

    二、输入语句

    1.使用Scanner类:

    (1)使用java.util包。  import java.util.*;

    (2)构造Scanner类对象,它附属于标准输入流System.in。   Scanner snew Scanner(System.in);

    (3)常用的next()方法系列:       nextInt():输入整数    nextLine():输入字符串     nextDouble():输入双精度数     next():输入字符串(以空格作为分隔符)。

    1. import java.util.*;  
    2. public class DEMO_1 {  
    3.     public static void main(String[] args){  
    4.         Scanner snew Scanner(System.in);  
    5.         System.out.print("输入你的姓名:");  
    6.         String name = s.nextLine();  
    7.         System.out.print("输入你的年龄:");  
    8.         int age = s.nextInt();  
    9.         System.out.println("姓名:" + name + "  年龄:" + age );  
    10.         s.close();         //若没有关闭Scanner对象将会出现警告  
    11.     }  

    注释:代码第1行创建了一个Scanner类的对象,这个对象是用来输入的。后面的代码是从控制台的输入中取出一个值,赋值给对应的变量。

    2.使用java.io.BufferedReaderjava.io.InputStreamReader

    步骤:

    (1)使用java.io包。  import java.io.*;

    (2)构造 BufferedReader类对象,它附属于标准输入流System.in。  

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    public class Sandbox4 extends Sandbox2{
        public static void main(String[] args) {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
            String str = null;  
            while(true){
                try {  
                    str = br.readLine();  
                }catch(IOException e){
                    e.printStackTrace();
                }
                if(str.equals("END"))break;
                System.out.print(str);
            }
        }
    }


    请注意:

    (1)read方法:读取单个字符。 返回:作为一个整数(其范围从 0 到 65535 (0x00-0xffff))读入的字符,如果已到达流末尾,则返回 -1 ;

    (2)readLine方法:读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。 返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null。

    3、使用java.io.Console

    public class Sandbox4 extends Sandbox2{
        public static void main(String[] args) {
            Console console = System.console();  
            if (console == null) {  
                throw new IllegalStateException("Console is not available!");  
            } 
            String str = null;
            while(true){
                str = console.readLine("请输入"); 
                if("END".equals(str))break;
                System.out.println(str);
            }        
        }
    }

     输入问题解惑:


    注:该问题图片来源于百度知道。

    三、输出语句

    Java中的输出语句有以下四种:

    System.out.println(1111);//换行打印
    System.out.print(1111);//不换行打印
    System.out.write(2222);//字节输出
    System.out.printf("%+8.3f\n", 3.14);//按格式输出
    1. System.out.println(); 是最常用的输出语句,它会把括号里的内容转换成字符串输出到输出窗口(控制台),并且换行,当输出的是一个基本数据类型时,会自动转换成字符串,如果输出的是一个对象,会自动调用对象的toString();方法,将返回值输出到控制台
    2. System.out.print(); 与第一个很相似,区别就是上一个输出后会换行,而这个命令输出后并不换行。
    3. System.out.printf(); 这个方法延续了C语言的输出方式,通过格式化文本和参数列表输出。





    展开全文
  • Java笔试面试题整理第八波

    万次阅读 多人点赞 2016-06-14 11:07:41
    本系列整理Java相关的笔试面试知识点,其他几篇文章如下:  Java笔试面试题整理第七波  Java笔试面试题整理第六波  Java笔试面试题整理第五波  Java笔试面试题整理第四波  Java笔试面试题整理第三...
    本系列整理Java相关的笔试面试知识点,其他几篇文章如下:

    1、运算符相关

    What results from the following code fragment?
    inti = 5;
    intj = 10;
    System.out.println(i + ~j);
    A、 Compilation error because”~”doesn’t operate on integers    B、-5    C、-6    D、15

    正确答案:C
    解法一:公式 -n=~n+1可推出~n=-n-1,所以~10=-11再加5结果为-6
    解法二:计算机中以 补码 存储。
    正数的原码/反码/补码相同 ,所以
    10存储为00000000 00000000 00000000 00001010  
    ~10的原码为11111111 11111111 11111111 11110101(10取反)
    ~10的反码为10000000 00000000 00000000 00001010(最高位符号位,不变,其余位取反)
    ~10的补码为10000000 00000000 00000000 00001011(负数的补码=反码+1)
    所以~10 = -11

    &&和&,||和|的区别:
        &&是逻辑与(短路与),当第一个判断条件不满足要求时(返回false),第二个判断条件就不会执行;只有当两个判断条件都返回true时,整个逻辑运算才返回true。
        &按位与,不论什么情况下,两边的判断条件都会执行,当两边都返回true时,按位与才返回true。

        ||逻辑或,当第一个判断条件返回true时,逻辑或直接返回true,第二个判断条件就不会执行了;
        |按位或,不论什么情况下,两边的判断条件都会执行,当有一个条件返回true时,按位或就返回true。

    注意:
        逻辑与、逻辑或两边的运算符必须是boolean类型的,而按位与、按位或可以是boolean类型,两边也可以是int类型的。
        当按位与、按位或两边是int类型时,将是通过二进制进行按位运算,规则就是:
        (1)按位与&:都为1时,返回1,其他情况返回0;
        (2)按位或|:有一个为1时,返回1,都为0时才返回0;
    如下例子:3&2=2,3|2=3
    3-->0011
    2-->0010
    &-->0010=2
    |-->0011=3

    2、泛型相关

    泛型在编译时期进行严格的类型检查, 消除了绝大多数的类型转换。泛型在集合中使用广泛,在JDK1.5之后集合框架就全部加入了泛型支持。在没有使用泛型之前,我们可以往List集合中添加任何类型的元素数据,因为此时List集合默认的元素类型为Object,而在我们使用的时候需要进行强制类型转换,这个时候如果我们往List中加入了不同类型的元素,很容易导致类型转换异常。如下例子:         
    List list = new ArrayList();
            list.add(18);
            list.add("lly");
            for(Object obj : list){
                int i = (int) obj;//此处运行后,将会报错
            }
        上面在将“lly”转成int时,会报 ClassCastException,但是在编译时却不会出错 。(在我们JDK1.5之后有了泛型之后,但是没有去使用泛型来定义集合,跟上面的一样效果。),同时,这也验证了我们前面总结异常类型时所说的,ClassCastException是属于运行时异常,也即非检查性异常。
    在我们使用泛型之后,可以避免不必要的转型,以及避免可能出现的ClassCastException,如下:         
    List<Integer> list = new ArrayList<Integer>();
            list.add(18);
            list.add("lly");    //此时,编译时就不能通过,报错!!!
    型允许我们在创建集合时就可以指定元素类型,当加入其他数据类型时,编译不能通过。泛型只作用于编译阶段,在编译阶段严格检查类型是否匹配,类型检查通过后,JVM会将泛型的相关信息擦出掉(即泛型擦除),也就是说, 成功编译过后的class文件中是不包含任何泛型信息的,泛型信息不会进入到运行时阶段
    如果像我们上面说的这样,那对于传进来的不同数据类型的对象也只会生成一个类型,而不是多种数据类型对象。下面我们可以验证一下:
    class Person<T> {
        private T charac;//人物特征
        public Person(T ch){
            this.charac = ch;
        }
        public T getCharac() {
            return charac;
        }
        public void setCharac(T charac) {
            this.charac = charac;
        }
    }
    测试:         
    Person<String> p1 = new Person<String>("lly");
            Person<Integer> p2 = new Person<Integer>(18);
            System.out.println("p1--->"+p1.getClass());
            System.out.println("p2--->"+p2.getClass());
    打印如下:
    p1--->class com.scu.lly.Person
    p2--->class com.scu.lly.Person
    可以看到,虽然我们传入了两种数据类型,但是在编译时并没有生成这两种类型,而都是Person类型,这正是因为我们上面所说的,泛型在编译通过后,确保了类型正确,此后就擦除了相关泛型信息,把所有元素都作为Person数据类型。也就是说,泛型类型在逻辑上我们可以看成是多个不同的数据类型,但是在本质上它只是同一种数据类型

    类型通配符:
    按我们上面的说法,泛型在编译成功后,泛型信息就被擦除,变成了同一个类型。那如何去区分原本具有父子类关系的泛型类型?如下例子:
    我们在上面Person类的基础上,进行测试:
    public class CommonTest {
        public static void main(String[] args) {
            Person<Number> p1 = new Person<Number>(12);
            Person<Integer> p2 = new Person<Integer>(18);
    
            getCharac(p1);
    
            getCharac(p2);//报错!!!编译不能通过,提示参数类型不符合
        }
    
        public static void getCharac(Person<Number> person){
            System.out.println(person.getCharac());
        }
    }
        按照我们的想法,因为Integer 是继承自Number的,根据Java多态的特性,我们调用getCharac(p2);应该是没有问题的,但是正是因为泛型擦除的特点,导致了泛型在编译通过后被擦除了泛型类型,在运行时,JVM根本不知道有Number和Integer这两个类型存在,内存中只会有Person对象存在。这也正是上面不能编译通过的原因。
        为了解决这个问题,也就是说在使用泛型的时候为了能够体现出父子关系(或者说兼容多态特性),提出了类型通配符的概念。类型通配符用 ? 来代替参数类型,代表任何类型的父类比如Person<?>就是Person<Number>和Person<Integer>的父类了,而Person<Number>和Person<Integer>是体现不出父类关系的,现在就可以继续使用多态特性了,如下:
        public static void getCharac( Person<?> person){
            System.out.println(person.getCharac());
        }
    将上面的参数类型改成通配符的形式以后,我们调用 getCharac(p2);就不会出错了。

    类型通配符上界和下界:
    继续我们上面的例子,我们的本意是getCharac方法中只能传入数字类型的参数过来,也就是说希望传入的类型参数是Number类型或它的子类,类型通配符上界提供了这种约束。
    类型通配符上界:可以这样定义:Person<? extends Number>,表示我们的参数类型最大是Number类型或者它的子类。继续修改我们的例子:
        public static void getCharac( Person<? extends Number> person){
            System.out.println(person.getCharac());
        }
    测试:
            Person<Number> p1 = new Person<Number>(12);
            Person<Integer> p2 = new Person<Integer>(18);
            Person<String> p3 = new Person<String>("lly");
            
            getCharac(p1);
            getCharac(p2);
            getCharac(p3);// 报错!!!编译不能通过,提示参数类型不符合
    因为String并不是Number的子类,因此上面也就不能编译通过了

    类型通配符下界:可以这样定义:Person<? super Number>,表示我们的参数类型最小是Number类型,或者是它的超类类型

    下面我们来看一个题目:
    Which three statements are true?
    class A {}
    class B extends A {}
    class C extends A {}
    class D extends B {}
    Which four statements are true ?
    A、The type List<A>is assignable to List.
    B、The type List<B>is assignable to List<A>.
    C、The type List<Object>is assignable to List<?>.
    D、The type List<D>is assignable to List<? extends B>.
    E、The type List<?extends A>is assignable to List<A>.
    F、The type List<Object>is assignable to any List reference.
    G、The type List<?extends B>is assignable to List<?extends A>.

    is assignable to(意为:赋给,转化为)
    正确答案:ACDG
    对于A任何使用了泛型的数据类型,都可以赋给没有使用泛型的数据类型,此时数据类型相当于是Object,如上面我们的一个例子:
        public static void getCharac( Person person){
            System.out.println(person.getCharac());
        }
        测试:
            Person<Number> p1 = new Person<Number>(12);
            Person<Integer> p2 = new Person<Integer>(18);
            Person<String> p3 = new Person<String>("lly");
            
            getCharac(p1);
            getCharac(p2);
            getCharac(p3);
    这个时候都能通过。

    由于使用泛型之后,父子关系必须要有通配符来解决。因此CDG正确。B错。

    对于E,说反了,因为上面的is assignable to赋予关系,体现的是多态关系(父子关系);
    对于F,和B一样的错误,虽然Object是任何类型的父类(需要跟A区别开来,A是用没用泛型的比较,这里是都用了泛型之后的比较),但是用了泛型后,父子关系要有通配符来体现。同样List<String>也不能转化为List<Object>。

    3、变量初始化问题

    对于成员变量:
    对于非final修饰的类的成员变量(包括static和非static),如果开发者没有给其赋初值,在编译时,JVM自动会给非final修饰的成员变量赋初值,我们在类的成员方法中就可以直接使用、运算了。
    对于final修饰成员变量,必须在(1)定义的时候初始化,(2)或者在构造方法中初始化(如果类中有多个构造方法,每个构造方法中都需要进行一次初始化),否则编译不通过。这是因为final类型的变量不能修改,必须在初始定义的时候或者new出对象时构造器里进行初始化,其他时候不能变更。

    对于非成员变量,即方法中的临时变量:
    方法中的临时变量,只需要在使用前保证了初始化就可以。不一定要在定义的时候就初始化,但必须要在开始使用这个变量前初始化。

    如下例子:
    public class VarTest {
        final int i ;
        public VarTest(){    //在构造方法中初始化了
            i = 3;
        }
        public VarTest(int n){ //有多个构造方法,必须在每个构造方法中进行初始化
            i = n;
        }
        public void doSomething() {
            int j;
            j = 1;//对于临时变量,如果这里不进行初始化,下面使用++j时编译不能通过
            System.out.println(++j + i);
        }
    
        public static void main(String[] args) {
            VarTest test = new VarTest();
            test.doSomething();
        }
    }

    4、suspend()和resume()方法

    Java.Thread的方法resume()负责重新开始被以下哪个方法中断的线程的执行()?
    A、stop    B、sleep    C、wait    D、suspend

    正确答案:D
    suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的 resume() 被调用,才能使得线程重新进入可执行状态

    5、几个需要注意的小知识点

    (1)What is the result of compiling and executing the following fragment of code:
    Boolean flag = false;
    if(flag = true){
        System.out.println(“true”);
    }else{
        System.out.println(“false”);
    }
    A、 The code fails to compile at the “if” statement.    B、 An exception is thrown at run-time at the “if” statement.
    C、 The text“true” is displayed.    D、 The text“false”is displayed.    E、 Nothing is displayed.

    正确答案:C
    这里主要是要注意,if条件判断中,flag = true先是一个赋值语句,赋值完成后,flag成为逻辑判断条件,会自动拆箱。

    (2)What will happen when you attempt to compile and run the following code?
    public class test{
    static{
       intx=5;
    }
    static int x,y;
    public static void main(String args[]){
       x--;
       myMethod( );
       System.out.println(x+y+ ++x);
    }
    public static void myMethod( ){
      y=x++ + ++x;
     }
    }
    A、compiletime error      B、prints:1      C、prints:2      D、prints:3      E、prints:7    F 、prints:8

    正确答案:D
    注意静态代码块中的语句声明,重新定义了一个局部变量int x = 5,执行完静态代码块后,局部变量就被销毁。此时全局变量x 还是默认值0,执行到打印语句时,x-1,y= 0,对于打印语句System.out.println(x+y+ ++x);中的x+y+ ++x由于+是左结合的,因此x+y+ ++x,即1+0+(++x).

    (3)以下代码将打印出
    public static void main (String[] args) { 
        String classFile = "com. jd. ". replaceA11(".", "/") + "MyClass.class";
        System.out.println(classFile);
    }
    A、 com. jd    B、 com/jd/MyClass.class    C、 ///MyClass.class    D、 com.jd.MyClass

    正确答案:C
    replaceAll方法的第一个参数是一个正则表达式,而"."在正则表达式中表示任何字符,所以会把前面字符串的所有字符都替换成"/"。如果想替换的只是".",那么久要写成"\\."。和replace类似,split()中的参数也是正则表达式,“.”也是关键词,如果想要使用也是要转义。即写成str.split("\\.")进行转义处理。

    (4)下面将打印出什么结果?  
    int b = 127;
                System.out.println(b);
                b = b++;
                System.out.println(b);
    A、127    B、128

    正确答案:A
    要特别注意: b = b++;和b = ++b;这种两种方式,实现b自增,在Java中是没有效果的。对于b = b++;b被赋予b++的结果,之后b并不会再来自增,因此打印127;对于b = ++b;b被赋予++b的结果,之后b也并不会再来自增,因此打印128。

    6、自动拆箱、装箱问题

    (1)下列 java 程序输出结果为______。
    inti=0;
    Integer j = newInteger(0);
    System.out.println(i==j);
    System.out.println(j.equals(i));
    A、true,false    B、true,true    C、false,true    D、false,false    E、对于不同的环境结果不同    F、程序无法执行

    正确答案:B
    对于==来说:
    如果运算符两边有一方是基本类型,一方是包装类型,在进行==逻辑判断时,包装类型会自动进行拆箱操作,因此i==j返回true;
    如果都是包装类型,那么==就是按照正常判断逻辑来,==比较的是对象的地址,但是下面这种情况除外:
        在-128至127这个区间,如果创建Integer对象的时候(1)Integer i = 1; (2) Integer i = Integer.valueOf(1); 如果是这两种情况创建出来的对象,那么其实只会创建一个对象,这些对象已经缓存在一个叫做IntegerCache里面了,所以==比较是相等的。 如果不在-128至127这个区间,不管是通过什么方式创建出来的对象,==永远是false,也就是说他们的地址永远不会相等。
    举例测试如下:
             Integer i1 = 8; 
             Integer i2 = 8; 
             Integer i3 = 300; //超过了127这个范围
             Integer i4 = 300; 
             Integer i5 = Integer.valueOf(8);
             Integer i6 = new Integer(8);
    //         System.out.println(i1 == i2);// true, 在 -128至127这个区间, Integer i = 1;和Integer i = Integer.valueOf(1); 这两种方式创建的对象相同
    //         System.out.println(i3 == i4);// false ,超过这个区间,创建出的是不同对象
    //         System.out.println(i1 == i5);// true , 在 -128至127这个区间, Integer i = 1;和Integer i = Integer.valueOf(1); 这两种方式创建的对象相同
             System.out.println(i1 == i6);// false ,在指定区间,只有上面两种方式创建出的对象才相同,通过new出来的是不相同的

    对于equals来说:
    equals不同的对象由不同的实现,对于Integer来说,equals比较的是值。因此,j.equals(i);返回的是true。

    (2)代码片段: 
    byte b1=1,b2=2,b3,b6; 
    final byteb4=4,b5=6; 
    b6=b4+b5; 
    b3=(b1+b2); 
    System.out.println(b3+b6);
    关于上面代码片段叙述正确的是()
    A、输出结果:13    B、语句:b6=b4+b5编译出错    C、语句:b3=b1+b2编译出错    D、运行期抛出异常

    正确答案:C
    被final修饰的变量是常量,这里的b6=b4+b5可以看成是b6=10;在编译时就已经变为b6=10了
    而b1和b2是byte类型,java中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过, 需要进行强制转换
    Java中的byte,short,char进行计算时都会提升为int类型。

    7、finally语句的执行是在return前还是return后

    在try的括号里面有return一个值,那在哪里执行finally里的代码?
    A、不执行finally代码    B、return前执行    C、return后执行
    正确答案:C
    finally语句是在try(或catch)的return语句执行之后,return返回之前执行。过程如 下: 在try中如果有return语句,他会首先检测是否有fianlly,如果有的话,就保存try中return要返回的值,然后执行finally中的方法,如果fianlly没有返回值,则finally方法执行完毕之后,返回执行try中的return方法,他会取出之前保存的return值,进行返回。
    如下例子:
    public static void main(String[] args) {
            intk = f_test();
            System.out.println(k);
        }
         
        public static int f_test(){
            inta = 0;
            try{
                a = 1;
                returna;
            }
            finally{
                System.out.println("It is in final chunk.");
                a = 2;
                returna;
            }
        }
    输出: 
    It is in final chunk.
    2

    如果将 return a ; 注释掉,尽管在finally中给a重新赋了值,但是结果将是如下输出
    It is in final chunk.
    1        
    说明,finally是在try中执行完return后再执行的。只有当finally中也有return的时候,方法将直接返回,不再执行热河代码。

    8、Java1.7和Java1.8的新特性

    一、对于JDK7
    1、支持将整数类型用二进制来表示,用0b开头    
     // 所有整数 int, short,long,byte都可以用二进制表示
        // An 8-bit 'byte' value:
        byte aByte = (byte) 0b00100001;
     
        // A 16-bit 'short' value:
        short aShort = (short) 0b1010000101000101;
     
        // Some 32-bit 'int' values:
        intanInt1 = 0b10100001010001011010000101000101;
        intanInt2 = 0b101;
        intanInt3 = 0B101; // The B can be upper or lower case.
     
        // A 64-bit 'long' value. Note the "L" suffix:
        long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
     
        // 二进制在数组等的使用
        final int[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001,
        0b00010011, 0b00100110, 0b01001100, 0b10011000 };

    2、switch语句支持String参数  
    String str = "a";
             switch (str) {
                case "a":
                    System.out.println("a---");
                    break;
                case "b":
                System.out.println("b---");
                break;
             }
    注意:在把字符串传进Switch case之前,别忘了检查字符串是否为Null。

    3、数字类型的下划线表示 更友好的表示方式,不过要注意下划线添加的一些标准,可以参考下面的示例    
     long creditCardNumber = 1234_5678_9012_3456L;
        long socialSecurityNumber = 999_99_9999L;
        float pi = 3.14_15F;
        long hexBytes = 0xFF_EC_DE_5E;
        long hexWords = 0xCAFE_BABE;
        long maxLong = 0x7fff_ffff_ffff_ffffL;
        byte nybbles = 0b0010_0101;
        long bytes = 0b11010010_01101001_10010100_10010010; 
        //float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
        //float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
        //long socialSecurityNumber1= 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix 
        //int x1 = _52;              // This is an identifier, not a numeric literal
        int x2 = 5_2;              // OK (decimal literal)
        //int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal
        int x4 = 5_______2;        // OK (decimal literal) 
        //int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix
        //int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number
        int x7 = 0x5_2;            // OK (hexadecimal literal)
        //int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number 
        int x9 = 0_52;             // OK (octal literal)
        int x10 = 05_2;            // OK (octal literal)
        //int x11 = 052_;            // Invalid; cannot put underscores at the end of a number 

    4、泛型实例的创建可以通过类型推断来简化 可以去掉后面new部分的泛型类型,只用<>就可以了
    一般使用泛型是如下情况:
    List<String> strList = new ArrayList<String>(); 

    在JDK7及以后,可以简化成如下:
    List<String> strList = new ArrayList<>(); 

    5、对资源的自动回收管理
    平常我们在使用一些资源时,一般会在finally中进行资源的释放,如下形式:
    BufferedReader br = new BufferedReader(new FileReader(path));  
    try {  
       return br.readLine();  
    } finally {  
       br.close();  
    } 
    而1.7之后我们可以使用这种形式:
    try (BufferedReader br = new BufferedReader(new FileReader(path)) {  
       return br.readLine();  
    } 
    直接在try中进行声明, 跟finally里面的关闭资源类似; 按照声明逆序关闭资源。这些资源都需要实现java.lang.AutoCloseable接口的资源。

    二、对于JDK1.8:
    1、接口中可以定义默认非抽象的方法

    Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:

     代码如下:
    interface Formula {
        double calculate(int a);
        default double sqrt(int a) {
            return Math.sqrt(a);
        }
    }
    Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用
    代码如下:
    Formula formula = new Formula() {
        @Override
        public double calculate(int a) {
            return sqrt(a * 100);
        }
    };
    formula.calculate(100);     // 100.0
    formula.sqrt(16);           // 4.0

    2、Lambda 表达式

    首先看看在老版本的Java中是如何排列字符串的:

    代码如下:
    List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
    Collections.sort(names, new Comparator<String>() {
        @Override
        public int compare(String a, String b) {
            return b.compareTo(a);
        }
    });
    只需要给静态方法 Collections.sort 传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法。

    在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:

    复制代码 代码如下:
    Collections.sort(names, (String a, String b) -> {
        return b.compareTo(a);
    });
    看到了吧,代码变得更段且更具有可读性,但是实际上还可以写得更短:
    复制代码 代码如下:
    Collections.sort(names, (String a, String b) -> b.compareTo(a));
    对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字,但是你还可以写得更短点:
    复制代码 代码如下:
    Collections.sort(names, (a, b) -> b.compareTo(a));
    Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型。

    3、Date API

    Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多,但又不完全一样,下面的例子展示了这组新API里最重要的一些部分:
    Clock 时钟

    Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。

    代码如下:
    Clock clock = Clock.systemDefaultZone();
    long millis = clock.millis();
    Instant instant = clock.instant();
    Date legacyDate = Date.from(instant);   // legacy java.util.Date

    4、支持多重注解

    9、异常抛出问题

    以下关于JAVA语言异常处理描述正确的有?
    A、throw关键字可以在方法上声明该方法要抛出的异常。    B、throws用于抛出异常对象。    
    C、try是用于检测被包住的语句块是否出现异常,如果有异常,则抛出异常,并执行catch语句。
    D、finally语句块是不管有没有出现异常都要执行的内容。    E、在try块中不可以抛出异常

    正确答案:CD
    throw用于抛出异常。
    throws 关键字可以在 方法上 声明该方法要抛出的异常,然后在 方法内部通过throw抛出异常对象

    未完待续~~

    参考文章:




    展开全文
  • Python语言的特点有哪些Python 是目前最流行的语言之一,从云计算、大数据到人工智能,Python 无处不在,Python 人才需求量也在逐年攀升,Python 为何能发展如此的迅猛,究竟有什么特点呢?Python 语言主要有以下...
  • java笔试题库-选择题 附带答案分析
  • java中哪些集合是线程安全的,哪些是线程安全的

    万次阅读 多人点赞 2019-05-09 11:41:42
    这里自己总结了一些比较常见的java集合,对于这些集合的特点和区别后期博客会进行总结介绍: 2.什么叫“集合是线程安全的” 当多个并发同时对非线程安全的集合进行增删改的时候会破坏这些集合的数据完整性; ...
  • JAVA面试】java面试题整理(3)

    千次阅读 2018-10-28 12:50:13
    java面试题整理(3) JAVA常考点3 目录 1. 讲下JAVA的运行时区域 1 2、简单说下垃圾回收机制 2 3、TCP和UDP的区别 7 4、项目是怎样预防sql注入的 7 5、 MySQL存储引擎的MyISAM和InnoDB区别 7 6、B树与B+树...
  • 那么python语言的特点有哪些呢?我们下面来说一下。Python语言主要有以下9个特点:(1)简单易学Python是一种代表简单主义思想的语言。阅读一个良好的 Python程序就感觉像是在读英语段落一样,尽管这个英语段落的语法...
  • 针对大学生或java免试群体的java复习资料和提纲
  • 下列Python语句非法的是 A. x = y =1 B. x = (y =1) C. x,y = y,x B. x=1;y=1 答案:B,C 7. 为了给整型变量x,y,z赋初值10,下面Python赋值语句正确的是 A. xyz=10 B. x=10 y=10 z=10 C. x=y=z=10 B. x=10,y...
  • 1.在Java中,负责对字节代码解释执行的是____。  A、垃圾回收器  B、虚拟机  C、编译器  D、多线程机制  2.下列叙述中,正确的是____。  A、Java语言的标识符是区分大小写的  B、源文件名与public类名可以...
  • java复习题库

    万次阅读 多人点赞 2018-11-12 22:09:17
    1:下列概念中不属于面向对象这种编程范畴的是()? A.对象消息 B.继承多态 C.类封装 D.过程调用 ?D 2:下面哪条语句把方法声明为抽象的公共方法()? A.public abstract method(); B.public ...
  • Java中的关键字(JDK1.8)

    千次阅读 2018-04-12 10:08:29
    注意 const和goto 是保留字。 true 、false、null不是关键字,而是常量标识。
  • 前端面试题

    万次阅读 多人点赞 2019-08-08 11:49:01
    以下哪个单词不属于javascript保留字:(B) 67 请选择结果为真的表达式:(C) 68 Javascript, 如果已知HTML页面的某标签对象的id=”username”,用____document.getElementById(‘username’)___ _方法...
  • 测试开发笔记

    万次阅读 多人点赞 2019-11-14 17:11:58
    能够最早的开展测试工作,降低修复成本,防止缺钱被扩大化(注意:加以重视:1公共的模块2全局性的数据结构3重要的使用频率较高的功能4以往项目经常出错的严重问题5复杂度较高的模块6当开发人员业务熟悉编码熟练...
  • 测试开发需要学习的知识结构

    万次阅读 多人点赞 2018-04-12 10:40:58
    动态分析的主要特点是当软件系统在模拟的或真实的环境执行之前、之和之后 , 对软件系统行为的分析。动态分析包含了程序在受控的环境下使用特定的期望结果进行正式的运行。它显示了一个系统在检查状态下是正确...
  • 下列哪项不属于jdk1.6垃圾收集器? A. Serail 收集器 B. parNew 收集器 C. CMS 收集器 D. G1 收集器 答案:D 解:Java垃圾收集器发展路径下图所示: 其中:G1收集器是在jdk1.7正式投入使用。 转载...
  • C#基础教程-c#实例教程,适合初学者

    万次阅读 多人点赞 2016-08-22 11:13:24
    C#基础教程-c#实例教程,适合初学者。...当然仅靠一章的内容就完全掌握C#语言是可能的,如需进一步学习C#语言,还需要认真阅读有关C#语言的专著。 1.1 C#语言特点 Microsoft.NET(以下简称.NET)框...
  • Java的六种线程状态(不是五种) ...
  • java虚拟机的内存区域划分

    千次阅读 2017-04-01 11:33:50
    Java虚拟机规范规定的java虚拟机内存其实就是java虚拟机运行时数据区,其架构如下: 其中方法区和堆是由所有线程共享的数据区。 虚拟机栈,本地方法栈和程序计数器是线程隔离的数据区。 二、详解 下面来具体介绍这...
  • 什么是Java?Java的三种技术体系架构有哪些? Java是一种计算机数据和一系列指令的集合. J2EE:企业级开发(目前都叫,JAVAEE) 是为开发企业级环境应用程序提供解决的一套解决方案,这个技术体系会用到Servlet,Jsp等...
  • JAVA复习题及答案

    2019-01-12 17:00:21
    3、下列选项,( )不属于Java语言的简单数据类型。 A.整数型 B.数组 C.字符型 D.浮点型 4、对于int a[ ]=new int[3],下列叙述错误的是( )。 A. a.length的值是3 B. a[1]的值是1 C. a[0]的值是0 D. a[a.length...
  • Java中的作用域有哪些

    千次阅读 2019-02-02 00:31:35
    2. Java中的作用域有哪些? 在Java语言中,变量的类型主要有3种:成员变量、静态变量和局部变量。 ①类的成员变量的作用范围与类的实例化对象的作用范围相同,当类被实例化时,成员变量就会在内存中分配空间并初始...
  • java面试题27 java中下面哪些是Object类的方法() A notify() B notifyAll() C sleep() D wait() 蒙蔽树上蒙蔽果,蒙蔽树下你和我。遇到这种题,我默默的打开了编译工具 Object类中方法: protected ...
  • Java 中文分词引擎对比

    千次阅读 2019-04-22 21:47:33
    本文包含基于Java的Ansj、jieba、word分词引擎的安装、简单调用、功能介绍。 一、jieba 源码:https://github.com/huaban/jieba-analysis 1、支持分词模式 * Search模式,用于对用户查询词分词 * Index模式,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,573
精华内容 16,629
关键字:

下列特点中不属于java的是

java 订阅