1.包装类
- 包装类的产生原因是针对8种数值型变量进行封装处理,为了解决8种基本数据类型不能被当做Object类型处理;
- 包装类:
Byte
Short
Integer
Long
Character
Float
Double
Boolean
- JDK 1.6提供了自动装箱和自动拆箱功能
- 自动装箱:可以把一个基本变量直接赋值给包装类或者Object类型;
- 自动拆箱:直接把包装类直接赋值给基本类型变量;
public class AutoBoxingUnboxing
{
public static void main(String[] args)
{
//包装类intObj
Integer inObj = 5;
// Object对象
Object boolObj = true;
// 自动拆箱ֱ
int it = inObj;
if (boolObj instanceof Boolean)
{
// 将Obj对象向下转型,再拆箱;
boolean b = (Boolean) boolObj;
System.out.println(b);
}
}
}
- 通过自动装箱和自动拆箱,基本类型可以被近似当成对象使用;
- 基本类型和字符串之间的转换方法:
public class Primitive2String
{
public static void main(String[] args)
{
var intStr = "123";
// 2种转换方法:
var it1 = Integer.parseInt(intStr); //除了Character以外都有
var it2 = Integer.valueOf(intStr);
System.out.println(it2);
var floatStr = "4.56";
var ft1 = Float.parseFloat(floatStr);
var ft2 = Float.valueOf(floatStr);
System.out.println(ft2);
var ftStr = String.valueOf(2.345f);
System.out.println(ftStr);
var dbStr = String.valueOf(3.344);
System.out.println(dbStr);
var boolStr = String.valueOf(true);
System.out.println(boolStr.toUpperCase());
// 向上转型直接转换为String
var itStr = 5 + "";
}
}
- 包装类的无符号运算:
public class UnsignedTest
{
public static void main(String[] args)
{
byte b = -3;
// 将b转换为无符号整数:
System.out.println(Byte.toUnsignedInt(b)); // 253
// ָ指定使用16进制解析无符号整数
var val = Integer.parseUnsignedInt("ab", 16);
System.out.println(val); // 输出171
// 将-12转换为无符号int型,然后转换为16进制表述的字符串
System.out.println(Integer.toUnsignedString(-12, 16)); // fffffff4
// 将两个数转换为无符号整数后删除
System.out.println(Integer.divideUnsigned(-2, 3));
// 将两个数转换为无符号整数后相除求余;
System.out.println(Integer.remainderUnsigned(-2, 7));
}
}
2.处理对象
1.打印对象和toString方法
- 当使用控制台打印对象的时候,打印出的是对象的toString方法的返回值;
- toString方法是Object类的固有方法,所有的Java类都有这个方法;
- 类的toString方法返回该对象的“类名+@+hashcode”;
- 自定义实现toString 方法
class Apple
{
private String color;
private double weight;
public Apple(){ }
public Apple(String color, double weight)
{
this.color = color;
this.weight = weight;
}
public void setColor(String color)
{
this.color = color;
}
public String getColor()
{
return this.color;
}
public void setWeight(double weight)
{
this.weight = weight;
}
public double getWeight()
{
return this.weight;
}
public String toString()
{
return color + weight;
}
}
public class ToStringTest
{
public static void main(String[] args)
{
var a = new Apple("苹果", 5.68);
System.out.println(a);
}
}
2.==和equal方法
- 当使用==来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数值类型,则只要两个变量值相等,为true;但是对于两个引用类型来说,只有他们指向的对象为同一个对象时,==判断才会返回true;
- equal方法和==方法没有区别,但是程序员可以通过重写equal方法来改变等价判断方法;String类就重写了equal方法,只要字符串内容一致,就返回true;
public class EqualTest
{
public static void main(String[] args)
{
var it = 65;
var fl = 65.0f;
// 输出true
System.out.println(it == fl);
var ch = 'A';
// 输出true
System.out.println(it == ch);
var str1 = new String("hello");
var str2 = new String("hello");
// 输出false
System.out.println(str1 == str2);
// 输出true
System.out.println(str1.equals(str2));
}
}
- 通常,重写equal方法要满足的条件:
- 自反性:对任意x,x.equal(x)一定是true;
- 对称性:对任意x和y,如果y.equal(x)返回true,那么x.equal(y)也返回true;
- 传递性:对x,y,z,如果x.equal(y) is true, y.equal(z) is true, then x.qual(z) is true;
- 一致性:对于x和y,如果对象中用于比较的信息没有变,那么无论调用x.equal(y)多少次,返回的结果都应该保持一致;
- 对任何不是null的x, x.equal(null)一定返回false;
3.类成员
- 使用static修饰的成员就是类成员,static可以修饰方法、变量和代码块,不能修饰构造方法;
- static修饰的成员只能通过类名调用,且在类定义的时候就会被分配内存;
- 如果一个类只能创建一个对象,称为单例成员,单例成员的构造详见设计模式中的单例设计模式:
4.final修饰符
- final可以用于修饰类,变量和方法;和C#中的sealed一样,final修饰的东西一旦获得初始值就不可改变;
- final定义的成员必须由程序员显示赋值,务必定义final的时候就直接赋值;
- final修饰基本类型时,值不能改变,但是final修饰引用类型时,仅仅是引用类型的地址值不能改变,内容可以改变;
- final修饰符的重要应用就是宏变量,可以在编译的时候直接确定下来,不用分配指向内存;
- final方法不可被重写;如果不希望父类方法被重写,可以使用final;
- final修饰的类不可以有子类;
5.抽象类
- 抽象类和抽象方法的定义:
- 抽象方法和抽象类必须使用abstract定义;
- 有抽象方法的类只能被定义为抽象类,抽象类里可以没有抽象方法;
- 抽象方法不能有方法体;
- 抽象类不能实例化;
- 抽象类可以包含成员,方法,构造体,初始化块、内部类;
- 定义一个抽象类:
public abstract class Shape
{
{
System.out.println("ִ执行Shape的初始化块");
}
private String color;
// 定义一个抽象方法
public abstract double calPerimeter();
public abstract String getType();
// 构造方法(只能子类调用)
public Shape(){}
public Shape(String color)
{
System.out.println("ִ形状是");
this.color = color;
}
// 常规方法
public void setColor(String color)
{
this.color = color;
}
public String getColor()
{
return this.color;
}
}
- 继承实现抽象类
public class Triangle extends Shape
{
private double a;
private double b;
private double c;
public Triangle(String color, double a, double b, double c)
{
super(color); //调用抽象类的构造方法
this.setSides(a, b, c);
}
//给三角形赋值三边;
public void setSides(double a, double b, double c)
{
if (a >= b + c || b >= a + c || c >= a + b)
{
System.out.println("这不是三角形");
return;
}
this.a = a;
this.b = b;
this.c = c;
}
// 计算周长
public double calPerimeter()
{
return a + b + c;
}
// 返回类型
public String getType()
{
return "三角形";
}
}
6.Java9改进的接口
1.接口的概念和定义
- 接口是一种规范,接口定义了某一批类需要执行的规范,也就是规定类里必须出现的方法;
- 定义一个接口:
[修饰符] interface 接口名 extends 父接口1,父接口2...
{
常量定义;
抽象方法定义;
内部类、接口、枚举;
私有方法、默认方法...
}
- 修饰符可以是public或者省略;如果省略,只能在相同包下访问接口;
- 一个接口可以有多个父接口,但是不能继承类;
- 接口里的成员变量只能是静态常量(默认public final static);方法默认是公共抽象方法;
2.接口的继承
- 子接口扩展父接口,会直接获得父接口中定义的所有常量和抽象方法;
interface InterfaceA
{
int PROP_A = 5;
void testA();
}
interface InterfaceB
{
int PROP_B = 6;
void testB();
}
interface InterfaceC extends InterfaceA, InterfaceB
{
int PROP_C = 7;
void testC();
}
public class InterfaceExtendsTest
{
public static void main(String[] args)
{
System.out.println(InterfaceC.PROP_A);
System.out.println(InterfaceC.PROP_B);
System.out.println(InterfaceC.PROP_C);
}
}
3.使用接口
- 接口的主要用途:
- 定义变量,也可用于强制类型转换;
- 调用接口中定义的常量;
- 被其他类发现;模拟多继承;
- 一个类可以实现多个接口;当类继承了接口的方法之后,它必须完全实现这个接口所定义的全部抽象方法,否则该类会成为抽象类;
4.接口和抽象类
- 接口是最终件(不可轻易改变),抽象类是中间件(改动对系统影响不大);
- 接口和抽象类的区别(201)
5.面向接口编程(详见各种设计模式)
7.内部类(205)
8.Lambda表达式(简化的匿名内部类)
- lambda表达式可以简化创建匿名内部类对象:
public class CommandTest
{
public static void main(String[] args)
{
var pa = new ProcessArray();
int[] target = {3, -4, 6, 4};
// 使用匿名内部类作为参数
pa.process(target, new Command()
{
public void process(int element)
{
System.out.println("数组元素的平方是:" + element * element);
}
});
}
}
public class CommandTest2
{
public static void main(String[] args)
{
var pa = new ProcessArray();
int[] array = {3, -4, 6, 4};
// 用lambda表达式进行改写:
pa.process(array, (int element)->{
System.out.println("����Ԫ�ص�ƽ����:" + element * element);
});
}
}
- lambda表达式的格式:
(形参列表)->{代码块}
只有一个形参可以省略();只有一条语句可以省略{}
lambda表达式会被当成任意类型的对象,取决于运行环境的需求;
- 例子:
interface Eatable
{
void taste();
}
interface Flyable
{
void fly(String weather);
}
interface Addable
{
int add(int a, int b);
}
public class LambdaQs
{
// 调用该方法需要Eatable对象;
public void eat(Eatable e)
{
System.out.println(e);
e.taste();
}
// 调用该方法需要Flyable对象
public void drive(Flyable f)
{
System.out.println("我正在驾驶" + f);
f.fly("天气清凉");
}
// 调用该方法需要Addable对象
public void test(Addable add)
{
System.out.println("5和3的和为" + add.add(5, 3));
}
public static void main(String[] args)
{
var lq = new LambdaQs();
lq.eat(() -> System.out.println("味道不错")); //实现了Eatable接口中的taste方法
lq.drive(weather -> {
System.out.println("今天的天气是" + weather); //实现了fly方法
System.out.println("ֱjdifjisjfisjdif");
});
// 代码块只有一条语句,即使该表达式需要返回值,也可以省略return关键字;
lq.test((a, b) -> a + b);
}
}
- lambda表达式的类型是“函数式接口类型”,函数式接口类型代表只包含一个抽象方法的接口;注解:@functionalInterface;
- lambda表达式的函数式接口;在lambada表达式中使用var;方法引用与构造器引用;lambda表达式与匿名内部类的区别;lambda表达式调用Arrays类方法;(226)
9.枚举类