Java入门阶段
Java三大版本含义
JavaSE(Java Standard Edition):标准版本,定位在个人计算机上使用。
JavaEE(Java Enterprise Edition):企业版,定位在服务器端的应用。【主流】
JavaME(Java Micro Edition):微型版,定位在消费性电子产品的应用上。
物联网的发展肯定会基于安卓开发。
Java的特性和核心优势
Java核心优势:跨平台和可移植性
特性:安全性、面向对象、简单性、高性能、分布式、多线程、健壮性。
Java应用程序的运行机制
Java首先利用文本编辑器编写Java源程序,源文件的后缀名为.java;再利用编译器(javac)将源程序变异成字节码文件,字节码文件的后缀名为.class;最后利用虚拟机(解释器,java)解释执行。
JRE是Java运行的环境,里边包含了包含Java虚拟机即JVM。
通过JVM,程序避免了直接和操作系统打交道,只需要和虚拟机打交道就可以,这是实现跨平台的一个核心机制。
JDK、JRE、JVM之间的区别
- JDK(Java Development Kit):java开发工具包,包含JRE,以及增加编译器和调试器,等于程序开发的文件。
- JRE(Java Runtime Environment):包含Java虚拟机、库函数、运行Java应用程序所必须的文件。
- JVM(Java Virtual Machine):虚拟的用于执行bytecode字节码的虚拟计算机,和操作系统打交道。
JDK=JRE+JAVA开发工具
JRE=JVM+lib类库
JAVA_HOME是当jdk版本改变的时候直接去修改这里边的环境变量,不用修改Path里的环境。
第一个Java程序
文件名:Welcome.java
public class Welcome{
public static void main(String[] args){
System.out.println("欢迎光临!");
}
}
Java运行原理:
(1)编写java源程序,扩展名.java
;
(2)cmd窗口输入:javac 源文件名.java
,对源代码进行编译,生成class字节码文件;
(3)输入命令:java HelloWorld
,对class字节码文件解释运行。
在练习和学习的过程中,错误是你难得的提高的机会哦 ~
不要畏惧错误哦,因为不犯错,就不可能成长!
细节分析:
java对大小写敏感;public是访问修饰符;class表示类,对象都是基于类的,一个源文件可以包含多个类,一个类就对应一个class文件,但一个源文件中只能声明一个public类,并且该类名必须和文件名一样。
最常用的DOS命令
cd:进入一个目录
cd … :进入父目录
dir:查看本目录下的文件列表和子目录列表
cls:清屏
Tab:自动补齐
上下键:查看敲过的命令
IntelliJ IDEA类似于Eclise的一个JAVA开发软件
变量
- 变量的本质:代表一个可操作的存储空间。
数据类型和运算符(视频)
Java基本语法——标识符、关键字和转义符、流程控制
- 标识符:赋予变量、类和方法等的名称。
语法规范:
(1)由字母、数字、下划线、美元符$组成;
(2)由字母、下划线或美元符开始;
(3)类名首字母大写、方法和变量首字母小写,其后驼峰;
(4)标识符不能是关键字、不能包含空格、不能包含特殊字符。 - 关键字:java自带的用于表示数据类型或供需构造的标识符,如public,double等。
- 分隔符包含:{}、[]、空格、圆点。
- 转义符:
特殊字符:3个
":双引号
':单引号
\:反斜线
控制字符:5个
’ 单引号字符
\ 反斜杠字符
\r 回车
\n 换行
\f 走纸换页
\t 横向跳格
\b 退格 - 流程控制:顺序、分支(if-else、switch)、循环(for、while、do-while)。
- 数组:是一个对象;存放相同数据类型;下标从0开始;数组特点:一致性、有序性、不可变性。
一维位数组的定义:元素数据类型[] 数组变量名
//动态初始化。new分配数组内存空间后,数组中的元素内容是数组类型的默认值。
int[] a = new int[3]; a[0] = 1; a[1] = 2; a[2] = 3
//静态初始化
int[] a = {1,2,3,4};
// 练习:判断101-200之间有多少个素数,并输出所有素数。(每8个换一行)
//素数:在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
public class CountPrime{
public static void main(String[] args){
int sum = 0;
for(int i=101;i<=200;i++){
int count=0;
for(int j=2;j<i;j++){ //将101~200之间的每一个数都计算一下其是不是素数
if(i%j == 0){
count++;
}
}
if(count == 0){
System.out.print(i+" "); //为素数则输出该值
//每8个换行,方便查看
sum+=1;
if(sum%8 == 0){
System.out.println();
}
}
}
System.out.println(sum); //输出所有素数个数
}
}
- Java的基本数据类型:8种基本类型、对应的包装类、引用数据类型及与String 之间的转换。
/**
* 基本数据类型 : 8种基本类型
* 对应的包装类 引用数据类型 及 与 String 之间的转换。
* String 基本数据类型 引用数据类型 之间的转换的联系 。
*
* String.valueOf() Integer.parseInt();
* valueOf()函数了,这个函数对于-128到127之间的数,会进行缓存
* @author Administrator
*
*/
public class TestWrapper {
@Test
public void StringtoWrapp(){
// 基本数据类型 == 包装类 ===String类 之间的转换。
// 基本数据类型 转换 String
int i =10;
Integer in =20;
String st= String.valueOf(i);
String st1= String.valueOf(in);
// 字符串转换为 ====基本数据类型 和 引用数据类型
int sf = Integer.parseInt(st);
System.out.println(sf);
System.out.println(in.toString());
}
@Test
public void tt(){
int in = 9;
System.out.println(in);
// 基本数据类型 ===》转换引用数据类型 , 直接调用引用类型的构造器
Integer ins= new Integer(in);
// 包装类 转换为基本数据类型 jdk 5.0 以后废弃 此法, 可以自己拆箱 装箱。
in = ins.intValue();
System.out.println(ins.toString());
Float f= new Float(23.4f);
System.out.println(f.toString());
Boolean ff =new Boolean("true");
Boolean f1 =new Boolean(true);
System.out.println(ff+":"+f1);
}
@Test
public void gg(){
// 【自动装箱】 基本数据类型直接赋值给 包装类
Integer fg= 13;
// 【自动拆箱】 -- 包装类 自动转换为 基本数据类型。
int fg1 =fg;
}
}
类和接口
Java面向对象的三大特性:封装、继承、多态
- 封装:对外部访问者将一些信息隐藏,通过该类提供的方法实现操作和访问;
- 继承:关键字extend。若类中没有使用extends关键字继承一个类,则这个类默认继承Object类;
- 多态:对象有多种形态。同一个行为具有多个不同的表现形式或形态。
多态的三个必要条件:继承、重写、父类引用指向子类对象:Patent p = new child();
类声明和定义:
java类声明格式:访问说明符 class 类名 extends 超类名 implements 接口名
访问说明符:为public或缺省,public定义的类可以被所有包访问;
类名:用户自定义;
超类名:指的是已经存在的类;
接口名:后边讲到
- java类体:包括成员变量、方法。
成员变量和方法的访问说明符有:public、private、protected。 - java中的接口:接口声明基本格式
public interface 接口名 extends 接口列表
(1)java语言中禁止多继承属性,但可以通过接口来帮助类扩展方法。
(2)接口中可以定义大量的常量和方法,但其中的方法只是一种声明,没有具体的实现,使用接口的类自己实现这些方法。
(3)接口与类的区别在于:接口没有变量的声明但可以定义常量;接口只有方法的声明没有方法的实现。
(4)接口的声明语法格式如下:
[可见度] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
- 构造函数: 也叫构造方法,是JAVA中一种特殊的函数,与函数名相同,无返回值。
构造函数作用:用作初始化成员属性和成员方法的,即new对象产生后就调用了对象的属性和方法,只运行一次。即对象一建立就运行构造函数,一般函数是对象调用才执行,一般函数可以被调用多次。
构造函数特点:(1)函数名与类名相同;(2)不用定义返回值类型;(3)不可以写return语句。 - 类的实例就是类对象,有状态和行为。
类中的两个特殊变量super
和this
。
(1)super
:类声明中用关键字extends扩展了其超类之后,super用在扩展类中引用其超类(父类)中的成员变量。
(2)this
:变量指向当前对象或者实例。
类中常用的两个关键字new
、static
、fanal
。
(1)new
:用于创建对象,在堆中开辟空间。
(2)static
:修饰的方法为类方法;修饰的变量为类变量。
(3)final
:修饰的类不能被继承;修饰的变量或常量不能被改变。
Collection接口
- 集合框架:
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:
(1) 接口: 是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
(2) 实现(类): 是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
(3) 算法: 是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
常用的类
(1)Map类:在java.util包中实现。HashMap
集合实现了Map接口,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步,是无序的。
(2)List类:是有序的。ArrayList
底层数据结构式数组结构,查询快,增删慢;LinkedList
底层是链表结构,查询慢,增删快。
(3)String相关类:
String类是final类。类中的成员方法否是final;String类是通过char数组来保存字符串的。
常用方法:
public String substring(int beginIndex, int endIndex) //获取某一位置到另一位置间的字符串
public String trim() //去除字符串中的空格
public String replace(char oldchar, char newchar) //替换指定字符串
public boolean equals(Object anObject) //比较两个字符串是否相等
public int length() //字符串长度
public int indexOf(String str) //字符串检索
当对字符串进行修改的时候,需要使用 StringBuffer
和 StringBuilder
类。和 String 类不同的是,StringBuffer
和 StringBuilder
类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuffer类提供了一个字符串可变系列,类似于String类,但它存储的字符序列可以任意修改,使用起来比String类灵活得多。常用构造函数:StringBuffer()
、StringBuffer(String str)
、将stringbuffer对象的数据转换成字符串:public String toString()
StringBuilder类
比较String、StringBuffer、StringBuilder:
运行速度:StringBuilder > StringBuffer > String
用法:
String
用于少量字符串的情况;
StringBuffer
适用于多线程下字符串缓冲区进行大量操作的情况,要求线程安全的情况;
StringBuilder
类适用于单线程下字符缓冲区进行大量操作的情况。
java常量池 :用于存储已被虚拟机加载的类信息、常量、静态常量等。常量池存储在堆中。
用双引号“”
创建字符串:首先会去常量池中寻找有没有相等的这个常量对象,没有的话就在常量池中创建这个常量对象;有的话就直接返回这个常量对象的引用。
intern
: 对于使用new创建的字符串对象,如果想将这个对象的引用加入到字符串常量池,可以使用intern方法。 调用intern后,首先检查字符串常量池中是否有该对象的引用,如果存在,则将这个引用返回给变量,否则将引用加入并返回给变量。
关于+
运算符:两个或者两个以上的字符串常量相加,在预编译的时候,“+”会被优化,相当于把两个或者两个以上字符串常量自动合成一个字符串常量。
字符串常量存储在方法区,字符串存储在堆中。
String str1="hello";
String str2 = "hello";
System.out.println(str1==str2);//true
public static void main(String[] args){
String s1 = new String("hello");
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); //false,因为==比较的是引用的地址,s2指向的是常量池中常量对象的地址,而s1指的是堆中String对象的地址。
System.out.println(s1.equals(2); //true,因为比较的是字符串的内容
System.out.println(s1 == s3); //false,因为每个String对象都是不同的,引用指向的对地址也不同
}
(4)Date相关类 :主要是对日期进行格式化
Date currentTime = new Date(); //使用当前日期和时间来初始化对象。
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss"); //使用 SimpleDateFormat 格式化日期
System.out.println("当前时间为: " + ft.format(currentTime)); //得到一个格式化的日期
SimpleDateFormat是一个非线程安全类。
(5)BigDecimal类
异常
Throwable类派生出两个类:Exception类和Error类。 其中Error类由系统保留,Exception类供程序使用。
//Exception类中常用的方法:
public String toString(); //返回异常的简短描述
public String getMessage() //返回异常的详细信息描述
异常又分为系统自定义的异常和用户自定义的异常,用户自定义异常继承自Exception。常见的系统异常:
数组下标越界异常:ArrayIndexOutOfBoundsException
算数异常类:ArithmeticExecption //比如出书为0了
ClassNotFoundException 未找到想要装载使用的类
NullPointerException 空的尚未分配内存的对象
throws
关键字、throw
关键字:
throws
关键字被应用在声明方法时,用来指定方法可能抛出的异常。
throw
关键字用于方法体中,并且抛出一个异常对象。throw抛出异常要在上一级中捕获并处理,必须在抛出异常的方法中使用throws方法声明要抛出的异常;若要捕捉,必须使用try-catch语句块。 throw一般用于用户自定义的异常。
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{ // 异常不异常finally都会执行(通常用语关闭文件流对象或者数据库对象等)
// 程序代码
}
自定义异常:
//需修改
class InputMismatchException extends Exception{
public InputMismatchException (){
super();
}
public InputMismatchException (String str){
super(str);
}
}
try{
Input = input.nextInt();
}catch(InputMismatchException e){
System.out.println("输入的字符不是数字!");
}
问题
1 括号的使用
- 使用new关键字,调用构造方法创建对象要加小括号
()
:Person p1 = new Person();
2 构造函数这些的执行顺序
- 若继承了父类,则加载顺序为:父类静态 --> 子类静态 --> 父类成员函数 --> 父类构造方法 --> 子类成员函数 --> 子类构造方法
其中,静态代码包括(静态方法,静态变量,静态代码块等),成员函数即(成员方法,成员变量,成员代码块等),同一种代码,写在上面的先加载。
3 成员变量和方法的访问说明符public、private、protected使用方法
- public:对所有类可见;
- protected:不能跨包访问,对同一包内的类和所有子类可见;
protected 需要从以下两个点来分析说明:
(1)子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
(2)子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。 - private:同一类内可见;
- default:在同一包内可见。
改错
关于java中的构造函数
- 构造函数没有返回值,返回类型也不是void;
- 构造函数必须和类名一样,可以带参数也可以不带参数;
- 一个类可以定义多个构造函数;
- 注意:类中若不声明构造函数,JVM(Java Virtual Machine)会帮我们默认生成一个空参数的构造函数;若类中我们声明了带参数列表的构造函数,JVM就不会帮我们默认生成一个空参数的构造函数,要想使用空参数的构造函数就需要自己去构造 因此:类中不用必须显式的定义构造函数。
- 构造函数作用:创建对象;对象初始化。
- 构造函数在继承中的特点:
- 子类会不会调用父类的函数?
答:子类继承父类,子类对象初始化时父类构造函数也会执行,因为子类需要使用父类中的属性。 - 子类的构造函数与父类构造函数有什么关系?
答:子类构造函数中默认的第一行有一条隐式语句super()
,该语句会访问父类中的空参数构造函数,除非父类中没有空参数的构造函数,此时子类构造函数的第一行必须显式调父类的构造函数,即super(int x, ...)
。 - 子类的构造函数需要注意些什么?
答:子类的构造函数中,super()
语句代表了父类的构造函数;this()
语句代表调用了子类自身的构造函数。若这两条语句显式写出来必须放在构造方法的第一行,并且这两条语句不能共存,一个构造函数中的第一行要么是this()要么是super()。 - 普通函数与构造函数的区别?参考文献
答:
(1)调用时期不同:构造函数在类的对象创建时就运行,而普通函数在对象调用时才会执行;
(2)执行次数不同:一个对象创建后,其构造函数只执行一次, 就是创建时执行;而普通函数在对象创建之后可以执行多次,取决于对象的调用次数。
(3)构造函数没有返回值,也不能用void来修饰,普通方法必须有返回值;
(4)命名规则上,构造函数一般是首字母大写并且要与类名一致,普通函数需要遵循小驼峰式命名;
(5)构造函数不能直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候才被调用的;
(6)构造函数在new的时候自动调用优先级高于普通方法。
//---------------------------文件:Math1.java------------------------------------
package demo;
public class Math1{
private int count;
//构造函数
public Math1(){
System.out.println("这是构造函数!");
}
//普通函数
public void math(){
System.out.println("这是普通方法");
}
public int add(){
count++;
return count;
}
public int getCount(){
return count;
}
public void setCount(int count){
this.count = count;
}
}
//---------------------------文件:Test.java------------------------------------
//测试函数
package demo;
import demo.Math1;
public class Text{
public static void main(String[] args){
//初始化a
Math1 a = new Math1();
//调用普通方法
a.math();
int count = a.getCount();
System.out.println(count);
a.add();
int count1 = a.getCount();
System.out.println(count1);
a.setCount(100);
int count2 = a.getCount();
System.out.println(count2);
}
}
//输出:
这是构造方法!
这是普通方法!
0
1
100
eclipse重命名java文件
- 点击该文件 - 按F2即可修改。
关于java中的线程类的实现方式
继承Thread类
- Thread类是所有线程类的父类,实现了对线程的抽取和封装。
- 继承Thread类创建并启动多线程的步骤:
①.定义一个类,继承自Thread类,并重写该类的run方法,该run方法的方法体就代表了线程需要完成的任务,因此,run方法的方法体被称为线程执行体
②.创建Thread子类的对象,即创建了子线程
③.用线程对象的start方法来启动该线程 - Demo
先创建一个售票线程java文件
package demo1;
public class SellTickets extends Thread{
//共享数据
static int count = 100;
//重写Thread类的run()方法
@Override
public void run(){
//循环售票
while(count>0){
count--;
System.out.println(Thread.currentThread().getName() + "售出了一张票,剩余" + count);
}
}
}
测试类java文件
import demo1.SellTickets;
public class TheadDemo {
public static void main(String[] args) {
//模拟四个售票员售票
SellTickets s1 = new SellTickets();
SellTickets s2 = new SellTickets();
SellTickets s3 = new SellTickets();
// System.out.println(s1.currentThread().getName()); //这个线程的名称是main
s1.start();
s2.start();
s3.start();
}
}
实现Runnable接口
- 实现Runnable接口这个方法常用,因为实现接口的方式比继承类的方式更加灵活,也能减少程序之间的耦合。
- 实现Runnable接口创建并启动多线程的步骤:
①.定义一个Runnable接口的实现类,并重写该接口中的run方法,该run方法的方法体同样是该线程的线程执行体
②.创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
③.调用线程对象的start方法来启动该线程 - Demo
public class SellTickets{
static int count = 100;
//创建Runnable实现类的实例
static Runnable r = new Runnable(){
//重写Runnable接口的run()方法
@Override
public void run(){
while(count > 0){
count--;
System.out.println(Thread.currentThread().getName() + "售出了 一张票,剩余" + count);
}
}
}
public static void main(String[] args){
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t3 = new Thread(r);
t1.start();
t2.start();
t3.start();
}
}
继承Thread
类 与 实现Runnable
接口 比较
- 继承
Thread
类
(1)编写简单,如果要访问当前的线程,除了可以通过Thread.currentThread()方式之外,还可以使用 super关键字;
(2)弊端:因为线程类已经继承了Thread类,则不能再继承其他类**【单继承】**。 - 实现
Runnable
接口的方式
(1)线程类只是实现了Runnable接口,还可以继承其他类**【一个类在实现接口的同时还可以继承另外一个类】**;
(2)可以多个线程共享同一个target对象,所以非常适合多个线程来处理同一份资源的情况;
(3)弊端:编程稍微复杂,不直观,如果要访问当前线程,必须使用Thread.currentThread()。
调用start()与run()方法的区别
- start()方法会新建一个线程,并且让这个线程执行run()方法。
Thread thread = new Thread();
thread.start();
- 调用run()也能正常执行。但是,却不能新建一个线程,而是在当前线程中调用run()方法,只是作为一个普通的方法调用。
Thread thread = new Thread();
thread.run();
- 建议:不要用run()来开启新线程,它只会在当前线程中,串行执行run()方法中的代码。