JAVA 基础
1. 数据类型
字节型 byte 1 字节 -128~127
短整型 short 2 字节 -32768~32767
整型 int 4 字节 -2147483648~2147483647
长整型 long 8 字节 -9223372036854775808L~9223372036854775807L
单精度浮 点型 float 4 字节 +/-3.4E+38F(6~7 个有效位)
双精度浮 点型 double 8 字节 +/-1.8E+308 (15 个有效位)
字符型 char 2 字节 ISO 单一字符集
布尔型 boolean 1 字节 true 或 false
2. 系统的内存可大略分为3个区域
系统(OS) 区、程序(Program) 区和数据(Data) 区。
3. 常量声明
使用final关键字
final double PI=3.141592
4. 无符号右移
>>> 无论最高位是0还是1, 左侧被移 空的高位都填入0。
移位运算符适用的数据类型有byte、 short、 char、 int和long
5. 隐士转换和显式转换
从低级类型向高级类型的转换, 系统将自动执行, 程序员无须进行任何操作
byte < short < int < long < float < double
显式转换 又叫强制转换
6. 支持foreach 类似于C++11 for
7. 字符串变量 可以 使用 switch case, C++ 不行
C++11 最大是将字符串转换成整数的常量
constexpr std::uint32_t hash_str_to_uint32(const char* data)
{
std::uint32_t h(0);
for (int i = 0; data && ('\0' != data[i]); i++)
h = (h << 6) ^ (h >> 26) ^ data[i];
return h;
}
translate(const char* target)
{
switch (hash_str_to_uint32(target))
{
case hash_str_to_uint32("keep"):
break;
case hash_str_to_uint32("zero"):
break;
case hash_str_to_uint32("replace"):
break;
case hash_str_to_uint32("invert"):
break;
}
}
8. 字符串对象String对象都是new 出来的
char text1[]={'1','2'};
String str1 =new String(text1);
String str2 =new String("123");
字符串函数
length() indexof() lastindexof() charAt() substring trim replace startwith endwith
字符串相等判断 不能使用"==" ,"=="是判断地址是否相同,应该使用equals
按照字典比较compareTo
toUpperCase toLowerCase
分割 split
格式化:String.format(format,args)
日期格式化
Date date = new Date(); // 创建Date对象date
String time = String.format("%tc", date); // 将date格式化
String form = String.format("%tF", date);
// 将格式化后的日期时间输出
System.out.println("全部的时间信息是:" + time);
System.out.println("年-月-日格式:" + form);
类型格式化
String str = String.format("%d", 400 / 2); // 将结果以十进制显示
String str2 = String.format("%b", 3 > 5); // 将结果以布尔形式显示
String str3 = String.format("%x", 200); // 将结果以十进制格式显示
若字符串经常改变 使用StringBuilder
9. 数组
import java.util.*;
import java.util.Arrays;
int month[ ] = new int[12];
int day[]=new int[]{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
填充 fill
拷贝 copyOf copyOfRange
查询 Arrays.binarySearch
10. java 权限修饰符
11. 静态数据与静态方法
作用通常是为了提供共享数据或方法, 如数学计算公式等, 以static声明并实现, 这样当需要使用时, 直接使用类名调用这些静态成员即可。 尽管使用这种方式调用静态成员比较方便, 但静态成员同样遵循着public、 private和protected修饰符的约束。
静态方法中不可以使用this关键字。
在静态方法中不可以直接调用非静态方法。
不支持静态局部变量
静态代码块: static代码块叫静态代码块,作用是对类进行初始化它随着类的加载进行初始化,而且随着类的加载而被执行并且只会执行一次。
如果是普通代码块,每次创建一个对象就执行一次。
public class TestC {
public static void main(String[] args) {
//2、创建子类对象实例时,父类也会被加载,而且父类先被加载,子类后被加载
new BBB();
}
}
class BBB extends AAA{
static{
System.out.println("BBB的静态代码块被调用");
}
}
class AAA{
static{
System.out.println("AAA的静态代码块被调用");
}
}
打印:
AAA的静态代码块被调用
BBB的静态代码块被调用
12. 垃圾回收
重载类的finalize()函数;对象设置为null.调用system.gc();
package Number;
//演示finalize的用法
public class Frist {
public static void main(String[] args) {
Car bmw = new Car("宝马");
//这时bmw对象就是一个垃圾,垃圾回收器就会回收(销毁)对象(就是释放它的堆内存,可以腾出来给别的对象用),在销毁对象前,会调用该对象的finalize方法
//程序员可以在finalize方法中,写自己的业务逻辑代码(比如释放资源: 数据库连接,or打开的文件...)
//如果程序员不重写finalize方法,那么就会调用Object类的finalize方法,即默认处理(Object类的finalize方法是什么也不干的,即Object类只是提供了这样一个机制,但并没有做实事)
//如果程序员重写finalize方法,就可以实现自己的逻辑
bmw = null;
System.gc(); //主动调用垃圾回收器
System.out.println("程序退出了...");
}
}
class Car{
private String name;
public Car(String name) {
this.name = name;
}
//重写finalize方法
@SuppressWarnings("deprecation")
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("我们销毁汽车" + name);
System.out.println("释放了某些资源...");
}
}
13. 包装类
每个基本类型都有包装类函数
Integer.parseInt(String) 将str类型转int类型
Integer.toString(456); // 获取数字的十进制表示
Integer.toBinaryString(456); // 获取数字的二进制表示
Integer.toHexString(456); // 获取数字的十六进制表示
Integer.toOctalString(456); // 获取数字的八进制表示
byteValue()
intValue()
shortValue() 返回short 类型值
compareTo()与另一个Integer进行比较
equals() 与另一个Interger比较是否相等
Integer a = new Integer(34);
byte b = a.byteValue(); //返回值byte
常量
int maxint = Integer.MAX_VALUE; // 获取Integer类的常量值
int minint = Integer.MIN_VALUE;
int intsize = Integer.SIZE;
Number类
抽象类Number是BigDecimal、 BigInteger、 Byte、 Double、 Float、Integer、 Long和Short类的父类, Number的子类必须提供将表示的数值转换为byte、 double、 float、 int、 long和short的方法。 例如,doubleValue()方法返回双精度值, floatValue()方法返回浮点值。
14. 数字处理类
包括DecimalFormat类(用于格式化数字) 、Math类(为各种数学计算提供了工具方法) 、 Random类(为处理随机数问题提供了各种方法) 、 BigInteger类与BigDecimal类(为所有大数字的处理提供了相应的数学运算操作方法)
DecimalFormat 数字格式化类
Math.cos
Math.sin
Math.random
Math.randomChar
随机类 Random
大数字运算类 BigInteger
核心技术
1.接口、继承、多态
java.lang.Object 所有类的基类
重写 就是在子类中将父类的成员方法的名称保留, 重写成员方法的实现内容, 更改成员方法的存储权限, 或是修改成员方法的返回值类型(重写时权限只能增大不能减小,比如父类是protected子类不能为private)
重构:只修改内容
在子类的构造方法中自动调用父类的无参构造方法
如果使用finalize()方法对对象进行清理, 需要确保子类finalize()方法的最后一个动作是调用父类的finalize()方法, 以保证当垃圾回收对象占用内存时, 对象的所有部分都能被正常终止。
class Parent { // 父类
Parent() {
System.out.println("调用父类的parent()构造方法");
}
}
class SubParent extends Parent { // 继承Parent类
SubParent() {
System.out.println("调用子类的SubParent()构造方法");
}
}
public class Subroutine extends SubParent { // 继承SubParent类
Subroutine() {
System.out.println("调用子类的Subroutine()构造方法");
}
public static void main(String[] args) {
Subroutine s = new Subroutine(); // 实例化子类对象
}
}
在Object类中主要包括clone()、 finalize()、 equals()、 toString()等方法, 其中常用的两个方法为equals()和toString()方法。Object类中的getClass()、 notify()、 notifyAll()、 wait()等方法不能被重写, 因为这些方法被定义为final类型。
2.java 向上转型与向下转型
猫咪本身是一种动物,cat是一个父类(Animal)的引用,指向的是一个子类(Cat)的实例,这种写法称之为向上转型,是使用多态的方法
Animal animal= new Cat();
向上转型只能使用公用的函数名
向下转型为恢复子类所有功能,只有向上转型过的对象才能向下转型
Cat cat=(Cat)animal;
package Number;
abstract class Fruit{
abstract void show();
}
class Apple extends Fruit{
@Override
public void show(){
System.out.println("apple");
}
public void eatApple(){
System.out.println("吃了一个apple");
}
}
class Orange extends Fruit{
@Override
public void show(){
System.out.println("orange");
}
public void eatOrange(){
System.out.println("吃了一个orange");
}
}
class Banana extends Fruit{
@Override
public void show(){System.out.println("banana");
}
public void eatBanana(){
System.out.println("吃了一个banana");
}
}
public class Frist {
public static void run(Fruit fruit){
System.out.print("水果名字:");
fruit.show();
if(fruit instanceof Apple){
Apple apple = (Apple) fruit;
apple.eatApple();
}else if(fruit instanceof Orange){
Orange orange = (Orange) fruit;
orange.eatOrange();
}else{
Banana banana = (Banana) fruit;
banana.eatBanana();
}
}
public static void main(String[] args) {
run(new Apple());
run(new Orange());
run(new Banana());
}
}
}
打印输出:
水果名字:apple
吃了一个apple
水果名字:orange
吃了一个orange
水果名字:banana
吃了一个banana
3.多态(向上转型):
package Number;
public class Quadrangle {
// 实例化保存四边形对象的数组对象
private Quadrangle[] qtest = new Quadrangle[6];
private int nextIndex = 0;
public void draw(Quadrangle q) { // 定义draw()方法,参数为四边形对象
if (nextIndex < qtest.length) {
qtest[nextIndex] = q;
System.out.println(nextIndex);
nextIndex++;
}
}
public static void main(String[] args) {
// 实例化两个四边形对象,用于调用draw()方法
Quadrangle q = new Quadrangle();
q.draw(new Square()); // 以正方形对象为参数调用draw()方法
// 以平行四边形对象为参数调用draw()方法
q.draw(new Parallelogramgle());
}
}
class Square extends Quadrangle { // 定义一个正方形类,继承四边形类
public Square() {
System.out.println("正方形");
}
}
// 定义一个平行四边形类,继承四边形类
class Parallelogramgle extends Quadrangle {
public Parallelogramgle() {
System.out.println("平行四边形");
}
}
4.抽象与接口
//抽象类定义 是对整体事物的抽象
public abstract class ClassName{
abstract void method();
}
//接口是对行为的抽象
public interface IterfaceName{
void method(); //public abstract是缺省的 ,必须是public
}
Java中不允许出现多重继承, 但使用接口就可以实现多重继承。 一个类可以同时实现多个接口, 因此可以将所有需要继承的接口放置在implements关键字后并使用逗号隔开。 但这可能会在一个类中产生庞大的代码量, 因为继承一个接口时需要实现接口中所有的方法。
多重继承的语法如下:
class 类名 implements 接口1,接口2,…,接口n
interface A{
void m1();
}
interface B{
void m2();
}
interface C{
void m3();
}
// 实现多个接口,其实就类似于多继承。
class D implements A,B,C{
接口也可以继承
interface X{
}
interface Y{
}
interface Z extends X,Y{ //接口和接口支持多继承
}
抽象类是半抽象的,有构造方法,只允许出现常量和抽象方法。类和类之间只能单继承,一个抽象类只能继承一个类(单继承)。
接口是完全抽象的,没有构造方法,接口和接口之间支持多继承,一个类可以同时实现多个接口
interface Alram {
void alarm();
}
abstract class Door {
void open();
void close();
}
class AlarmDoor extends Door implements Alarm {
void oepn() {
//....
}
void close() {
//....
}
void alarm() {
//....
}
}
类的高级特性
1.类包 Java包的命名规则是全部使用小写字母。
Java 为了解决名字冲突,采用包名来区分,类似于C++命名空间
2.导入静态成员
使用import导入静态成员的语法如下
import static 静态成员名字
package com.lzw;
import static java.lang.Math.*;
import static java.lang.System.*;
public class ImportTest {
public static void main(String[] args) {
// 在主方法中可以直接使用这些静态成员
out.println("1和4的较大值为:" + max(1, 4));
}
}
3. final
final成员变量
基本类型 在声明赋值
对象 只能指向一个对象 不能改变指向
一个既是static又是final的字段只占据一段不能改变的存储空间
final 方法
final的方法不能被重写, 可以防止子类修改该类的定义与实现方式
private的方法隐式被指定为final类型, 因此无须将一个定义为private的方法再定义为final类型。
package Number;
class Parents {
private final void doit() {
System.out.println("父类.doit()");
}
final void doit2() {
System.out.println("父类.doit2()");
}
public void doit3() {
System.out.println("父类.doit3()");
}
}
class Sub extends Parents {
public final void doit() { // 在子类中定义一个doit()方法
System.out.println("子类.doit()");
}
// final void doit2(){ //final方法不能覆盖
// System.out.println("子类.doit2()");
// }
public void doit3() {
System.out.println("子类.doit3()");
}
}
public class FinalMethod {
public static void main(String[] args) {
Sub s = new Sub(); // 实例化
s.doit(); // 调用doit()方法
Parents p = s; // 执行向上转型操作
// p.doit(); //不能调用private方法
p.doit2();
p.doit3();
}
}
打印输出:
子类.doit()
父类.doit2()
子类.doit3()
final 类
如果一个类被设置为final,那么该类所有方法和成员隐式的被设置为final
4.内部类
内部类可分为成员内部类、 局部内部类以及匿名类
4.1成员内部类
内部类的实例一定要绑定在外部类的实例上,
在内部类中可以随意使用外部类的成员方法以及成员变量, 尽管这些类成员被修饰为private
在实例化内部类对象时, 不能在new操作符之前使用外部类名称实例化内部类对象, 而是应该使用外部类的对象来创建其内部类的对象
public class OuterClass {
innerClass in = new innerClass(); // 在外部类实例化内部类对象引用
public void ouf() {
in.inf(); // 在外部类方法中调用内部类方法
}
class innerClass {
innerClass() { // 内部类构造方法
}
public void inf() { // 内部类成员方法
}
int y = 0; // 定义内部类成员变量
}
public innerClass doit() { // 外部类方法,返回值为内部类引用
// y=4; //外部类不可以直接访问内部类成员变量
in.y = 4;
return new innerClass(); // 返回内部类引用
}
public static void main(String args[]) {
OuterClass out = new OuterClass();
// 内部类的对象实例化操作必须在外部类或外部类中的非静态方法中实现
OuterClass.innerClass in = out.doit();
//应该使用外部类的对象来创建其内部类的对象
OuterClass.innerClass in2 = out.new innerClass();
}
}
如果外部类的成员变量和内部类的成员变量名称一样,可以使用this关键字来区分
public class TheSameName {
private int x;
private class Inner {
private int x = 9;
public void doit(int x) {
x++; // 调用的是形参x
this.x++; // 调用内部类的变量x
TheSameName.this.x++; // 调用外部类的变量x
}
}
}
4.2局部内部类
类的方法或任意的作用域中均可以定义内部类
package Number;
interface OutInterface2 { // 定义一个接口
void printfName();
}
class OuterClass3 {
public OutInterface2 doit(final String x) { // doit()方法参数为final类型
// 在doit()方法中定义一个内部类
class InnerClass2 implements OutInterface2 {
private String prefixStr="Hello ";
InnerClass2(String s) {
prefixStr += x;
}
@Override
public void printfName() {
// TODO 自动生成的方法存根
System.out.println(prefixStr);
}
}
return new InnerClass2("doit");
}
public static void main(String[] args) {
OuterClass3 outInterface3= new OuterClass3();
OutInterface2 outInterface2=outInterface3.doit("123");
outInterface2.printfName();
}
}
打印输出: hello 123
4.3 匿名内部类
本质上是一个没有名字的局部内部类,定义在方法中、代码块中。一个接口/类的方法的某个实现方式在程序中只会执行一次,但为了使用它,我们需要创建它的实现类/子类去实现/重写。此时可以使用匿名内部类的方式,可以无需创建新的类,减少代码冗余。
匿名内部类是唯一一种无构造方法类
package Number;
public class Test {
public static String myname="dukai";
public static void main(String[] args) {
//使用匿名内部类替代学生类,创建的类型是new的那个类的子类
Swimming s = new Swimming() {
@Override
public void Swim() {
System.out.println(myname +"学生游的很快"); //myname 必须为静态
}
};
go(s);
}
public static void go(Swimming s)
{
System.out.println("开始游泳了~~");
s.Swim();
System.out.println("结束游泳了~~");
}
}
//定义一个接口规范游泳
interface Swimming{
void Swim();
}
不用继承Swimming来创建新类,直接new Swimming接口名并实现接口方法。
4.4 静态内部类
静态内部类中可以声明static成员,对象不可以使用外部类的非静态成员,如果创建静态内部类的对象, 不需要其外部类的对象
非静态内部类中不可以声明静态成员。
异常处理
1. 异常捕获
e.getMessage()函数: 输出错误性质。
e.toString()函数: 给出异常的类型与性质。
e.printStackTrace()函数: 指出异常的类型、 性质、 栈层次及出现
在程序中的位置。
2.自定义异常
用户只需继承Exception类即可自定义异常类。
在程序中使用自定义异常类, 大体可分为以下几个步骤:
(1) 创建自定义异常类。
(2) 在方法中通过throw关键字抛出异常对象。
(3) 如果在当前抛出异常的方法中处理异常, 可以使用try-catch语
句块捕获并处理, 否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常, 继续进行下一步操作。
public class MyException extends Exception {//创建自定义异常,继承Exception类
public MyException(String ErrorMessagr) { // 构造方法
super(ErrorMessagr); // 父类构造方法
}
}
public class Tran { // 创建类
// 定义方法,抛出异常
static int avg(int number1, int number2) throws MyException {
if (number1 < 0 || number2 < 0) { // 判断方法中参数是否满足指定条件
throw new MyException("不可以使用负数"); // 错误信息
}
if (number1 > 100 || number2 > 100) { // 判断方法中参数是否满足指定条件
throw new MyException("数值太大了"); // 错误信息
}
return (number1 + number2) / 2; // 将参数的平均值返回
}
public static void main(String[] args) { // 主方法
try { // try代码块处理可能出现异常的代码
int result = avg(102, 150); // 调用avg()方法
System.out.println(result); // 将avg()方法的返回值输出
} catch (MyException e) {
System.out.println(e); // 输出异常信息
}
}
}
集合类
需要导入java.util包
1.ArrayList和map
package Number;
import java.util.*;
public class Test { // 创建类
public void listIterator() {
ArrayList<String> list= new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用 For-Each 遍历 List
for (String str : list) { //也可以改写 for(int i=0;i<list.size();i++) 这种形式
System.out.println(str);
}
System.out.println("-------------------");
Iterator<String> ite=list.iterator();
while(ite.hasNext())//判断下一个元素之后有值
{
System.out.println(ite.next());
}
}
public void mapIterator() {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
//第三种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
}
public static void main(String[] args) {
Test test =new Test();
test.listIterator();
test.mapIterator();
}
}
2. HashSet 不允许存在一样的元素
package Number;
// 引入 HashSet 类
import java.util.HashSet;
import java.util.Iterator;
public class RunoobTest {
public static void main(String[] args) {
HashSet<String> sites = new HashSet<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
sites.add("Runoob"); // 重复的元素不会被添加
for (String i : sites) {
System.out.println(i);
}
System.out.println("-------");
Iterator<String> ite=sites.iterator();
while(ite.hasNext())//判断下一个元素之后有值
{
System.out.println(ite.next());
}
}
}
IO 输入与输出
1.输入流
所有输入流类都是抽象类InputStream(字节输入流) 或抽象类Reader(字符输入流) 的子类; 而所有输出流都是抽象类OutputStream(字节输出流) 或抽象类Writer(字符输出流) 的子类。
InputStream是用来处理字节的, 并不适合处理字符文本。 Java为字符文本的输入专门提供了一套单独的类Reader, 但Reader类并不是InputStream类的替换者, 只是在处理字符串时简化了编程。 Reader类是字符输入流的抽象类, 所有字符输入流的实现都是它的子类.
2. 输出流
OutputStream类是字节输出流的抽象类, 此抽象类是表示输出字节流的所有类的超类。
Writer类是字符输出流的抽象类, 所有字符输出类的实现都是它的子类
3. File类
4. FileInputStream与FileOutputStream类(字节流)
import java.io.*;
public class FileTest { // 创建类
public static void main(String[] args) { // 主方法
File file = new File("word.txt"); // 创建文件对象
try { // 捕捉异常
// 创建FileOutputStream对象
FileOutputStream out = new FileOutputStream(file);
// 创建byte型数组
byte buy[] = "我有一只小毛驴,我从来也不骑。".getBytes();
out.write(buy); // 将数组中信息写入到文件中
out.close(); // 将流关闭
} catch (Exception e) { // catch语句处理异常信息
e.printStackTrace(); // 输出异常信息
}
try {
// 创建FileInputStream类对象
FileInputStream in = new FileInputStream(file);
byte byt[] = new byte[1024]; // 创建byte数组
int len = in.read(byt); // 从文件中读取信息
// 将文件中信息输出
System.out.println("文件中的信息是:" + new String(byt, 0, len));
in.close(); // 关闭流
} catch (Exception e) {
e.printStackTrace(); // 输出异常信息
}
}
}
5. FileReader和FileWriter类(字符流)
package Number;
import java.io.*;
public class FileTest { // 创建类
public static void main(String[] args) { // 主方法
File file = new File("word.txt"); // 创建文件对象
try { // 捕捉异常
// 创建FileOutputStream对象
FileWriter out = new FileWriter(file);
// 创建byte型数组
String buy = "我有一只小毛驴,我从来也不骑。";
out.write(buy); // 将数组中信息写入到文件中
out.close(); // 将流关闭
} catch (Exception e) { // catch语句处理异常信息
e.printStackTrace(); // 输出异常信息
}
try {
// 创建FileInputStream类对象
FileReader in = new FileReader(file);
char byt[] = new char[1024]; // 创建byte数组
int len = in.read(byt);
// 将文件中信息输出
System.out.println("文件中的信息是:" + new String(byt, 0, len));
in.close(); // 关闭流
} catch (Exception e) {
e.printStackTrace(); // 输出异常信息
}
}
}
JAVA 反射
JAVA 枚举类型
1.定义常量可以用static+final或枚举类型
valueOf 将普通字符串转成枚举类型
compareTo函数用于枚举类的比较,大于为1等于为0,小于为-1
ordinal() 获取枚举的索引位置
import static java.lang.System.*;
public class EnumMethodTest {
enum Constants2 { // 将常量放置在枚举类型中
Constants_A, Constants_B
}
// 定义比较枚举类型方法,参数类型为枚举类型
public static void compare(Constants2 c) {
// 根据values()方法返回的数组做循环操作
for (int i = 0; i < Constants2.values().length; i++) {
// 将比较结果返回
out.println(c + "与" + Constants2.values()[i] + "的比较结果为:"
+ c.compareTo(Constants2.values()[i]));
if(c.compareTo(Constants2.values()[i])==0)
System.out.println("c 索引位置为:"+c.ordinal());
}
}
// 在主方法中调用compare()方法
public static void main(String[] args) {
compare(Constants2.valueOf("Constants_B"));
}
}
输出
Constants_B与Constants_A的比较结果为:1
Constants_B与Constants_B的比较结果为:0
2. 枚举的构造方法
可以添加构造方法,但是必须是private类型
package Number;
import java.lang.System.*;
import static java.lang.System.*;
public class EnumIndexTest {
enum Constants2 { // 将常量放置在枚举类型中
Constants_A("我是枚举成员A"), // 定义带参数的枚举类型成员
Constants_B("我是枚举成员B"),
Constants_C("我是枚举成员C"),
Constants_D(2);
private String description;
private int i = 4;
private Constants2() {
}
// 定义参数为String型的构造方法
private Constants2(String description) {
this.description = description;
}
private Constants2(int i) { // 定义参数为整型的构造方法
this.i = this.i + i;
}
public String getDescription() { // 获取description的值
return description;
}
public int getI() { // 获取i的值
return i;
}
}
public static void main(String[] args) {
for (int i = 0; i < Constants2.values().length; i++) {
out.println(Constants2.values()[i] + "调用getDescription()方法为:"
+ Constants2.values()[i].getDescription());
}
for (int i = 0; i < Constants2.values().length; i++) {
out.println(Constants2.values()[i] + "调用getI()方法为:"
+ Constants2.values()[i].getI());
}
}
}
打印输出:
Constants_A调用getDescription()方法为:我是枚举成员A
Constants_B调用getDescription()方法为:我是枚举成员B
Constants_C调用getDescription()方法为:我是枚举成员C
Constants_D调用getDescription()方法为:null
Constants_A调用getI()方法为:4
Constants_B调用getI()方法为:4
Constants_C调用getI()方法为:4
Constants_D调用getI()方法为:6
JAVA 泛型
1.泛型类似于C++的模板类
可以定义多种类型
import java.util.*;
public class MutiOverClass<K, V> {
public Map<K, V> m = new HashMap<K, V>(); // 定义一个集合HashMap实例
// 设置put()方法,将对应的键值与键名存入集合对象中
public void put(K k, V v) {
m.put(k, v);
}
public V get(K k) { // 根据键名获取键值
return m.get(k);
}
public static void main(String[] args) {
// 实例化泛型类对象
MutiOverClass<Integer, String> mu
= new MutiOverClass<Integer, String>();
for (int i = 0; i < 5; i++) {
// 根据集合的长度循环将键名与具体值放入集合中
mu.put(i, "我是集合成员" + i);
}
for (int i = 0; i < mu.m.size(); i++) {
// 调用get()方法获取集合中的值
System.out.println(mu.get(i));
}
}
}
常用泛型类集合
限制泛型可用的类:
class 类名称<T extends anyClass>
anyClass可以是 List String Integer
使用泛型类型通配符的语法如下:
泛型类名称<? extends List> a=null;
JAVA 多线程
1.JAVA多线程实现
JAVA多线程实现的三种方式
通过实现 Runnable 接口;
通过继承 Thread 类本身;
优先级:
线程的优先级每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
package Number;
public class MutiThreads {
public class DisplayMsgRunnable implements Runnable {
private String message;
private int sleepTime=5;
public DisplayMsgRunnable(String message) {
this.message = message;
}
public void run() {
while(sleepTime>0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(message+"**"+sleepTime);
sleepTime--;
}
}
}
public class DisplayMsgThread extends Thread{
private String message;
private int sleepTime=3;
public DisplayMsgThread(String message) {
this.message = message;
}
public void run() {
while(sleepTime>0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(message+"--"+sleepTime);
sleepTime--;
}
}
}
//可以创建方法2
public DisplayMsgRunnable getRunable(String msg) {
return new DisplayMsgRunnable("kai");
}
public DisplayMsgThread getThread(String msg) {
return new DisplayMsgThread("kai");
}
public static void main(String[] args) {
MutiThreads mutiThreads = new MutiThreads();
MutiThreads.DisplayMsgRunnable displayMsgRunable = mutiThreads.new DisplayMsgRunnable("kai");
Thread displayMsgThread1 = new Thread(displayMsgRunable);
MutiThreads.DisplayMsgThread displayMsgThread2 = mutiThreads.new DisplayMsgThread("du");
displayMsgThread1.start();
displayMsgThread2.start();
try {
displayMsgThread1.join();
displayMsgThread2.join();
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("app exit!");
}
}
2.线程同步
同步块
synchronized (同步的对象){
同步的代码
}
同步方法
当某个对象调用了同步方法时, 该对象上的其他同步方法必须等待该同步方法执行完毕后才能被执行
synchronized void f(){
}
package Number;
class Account{
private String accountNo;
private double balance;
public Account(String accountNo, double balance) {
this.accountNo = accountNo;
this.balance = balance;
}
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
class DrawThread extends Thread{
private Account account;
private double drawMoney;
private String drawName;
public DrawThread(String name,Account account,double drawMoney){
super(name);
this.drawName=name;
this.account = account;
this.drawMoney = drawMoney;
}
@Override
public void run() {
synchronized (this.account){
if (this.account.getBalance() >= this.drawMoney){
System.out.println(this.getName()+" 取钱成功,取出金额:"+this.drawMoney);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.account.setBalance(this.account.getBalance() - this.drawMoney);
System.out.println("余额为:"+this.account.getBalance());
}else{
System.out.println(this.getName()+" 取钱金额不足,剩余:"+this.account.getBalance());
}
}
}
}
public class DrawMoneyThread {
public static void main(String[] args) {
Account account = new Account("123",1000);
DrawThread drawThread = new DrawThread("张三",account,600);
DrawThread drawThread1 = new DrawThread("李四",account,600);
drawThread.start();
drawThread1.start();
}
}