Java 的包装类
- 包装类:可以把8个基本类型的值包装成对象使用
- 自动拆箱:包装类对象赋给对应的基本类型变量
- 自动装箱:基本类型变量赋给对应的包装类引用变量
- 基本数据和对应的包装类关系:
基本数据类型 包装类
byte--------------------------------------------Byte
short-------------------------------------------Short
int-----------------------------------------------Integer
long---------------------------------------------Long
char--------------------------------------------Character
float--------------------------------------------Float
double-----------------------------------------Double
Boolean---------------------------------------Boolean - 包装类可实现基本类型变量和基本字符串之间的转换:
- 利用包装类提供的parseXxx(String s)静态方法 (除了Character外)
- 利用包装类提供的Xxx(String s)构造器。
- String类提供了多个重载valueOf()方法,用于将基本类转换成字符串
/*包装类*/
class Primitive2String
{
public static void main(String[] args)
{
String intStr = "123";
//把一个特定字符串转换成int变量
int it1 = Integer.parseInt(intStr);
int it2 = new Integer(intStr);
System.out.println(it2);
//把一个特定字符串转换成float变量
String floatStr = "4.56";
float ft1 = Float.parseFloat(floatStr);
float ft2 = new Float(floatStr);
System.out.println(ft2);
//把一个float转换String类型。
String ftStr = String.valueOf(2.34f);
System.out.println(ftStr);
//把一个double型的转换成String类型
String doStr = String.valueOf(3.344);
System.out.println(doStr);
//把一个boolean变量转换成String类型
String boolStr = String.valueOf(true);
System.out.println(boolStr.toUpperCase());
}
}
结果:
123
4.56
2.34
3.344
TRUE
处理对象
- 打印对象和toString()方法
当直接用输出语句打印一个对象时
输出的格式:类名+@+hashCode
这是因为每个对象里面有一个默认的toString方法,上面的结果是toString方法的返回值。
比如下面的代码是相同的:
System.out.println§;
System.out.println(p.toString());
- toString()是Object里的一个实例方法,所有的java类都是Object的子类,因此所有的java对象都具有toString()方法。
- toString()方法是一个自我描述的方法。当程序员打印该对象时,系统就会输出该对象的自我描述。告诉外界该对象具有的信息。
- 一般情况下,都要重写toString()方法
==和equals方法
- 判断变量是否相等有两种方式
- ==
- equals方法。
- 对于数值只要相等 就返回 true
- 对于引用类型,只有他们指向同一个对象 ==判断才会返回true
- ==不能用于比较类型上没有父子关系的两个对象。
- equals方法是Object提供的一个实例方法 ,一般情况下和==无区别
- 当用户需要自定义判断方法是 ,可以重写equals()方法来实现。
- 而String类已经重写了equals方法,String的equals方法判断是两个字符串相等的标准是,只要两个字符串包含的字符序列相同 就返回true 否则返回false。
/*equals方法重写*/
class Person
{
private String name;
private String idStr;
public Person(){}
public Person(String name,String idStr)
{
this.name = name;
this.idStr=idStr;
}
public String getIdStr()
{
return idStr;
}
public void setIdStr(String idStr)
{
this.idStr = idStr;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//这里重写equals方法
public boolean equals(Object obj)
{
//相同的对象
if (this == obj)
{
return true;
}
//当obj为person的对象时
if (obj != null && obj.getClass() == Person.class)
{
Person personObj = (Person)obj;
//并且当idStr与obj对象的idStr相同时才可判断两者相同
if (this.getIdStr().equals(personObj.getIdStr()))
{
if (this.getName().equals(personObj.getName()))
{
return true;
}
return false;
}
return false;
}
return false;
}
}
class OverrideEqualsRight
{
public static void main(String[] args)
{
Person p1 = new Person("XXX","04161032");
Person p2 = new Person("XXX","04161032");
Person p3 = new Person("ZZZ","04161020");
//判断
System.out.println("p1是否与p2相等?"+p1.equals(p2));
System.out.println("p1是否与p3相等?"+p1.equals(p3));
}
}
结果:
p1是否与p2相等?true
p1是否与p3相等?false
- 这里要求写equals方法是满足 自反性 对称性 传递性 一致性 对于任意不是null的x 则x.equals(null)一定返回false。
final关键字
- final修饰类 则该类不能被继承
- final修饰方法 则该方法不能被覆盖或者重写
- final修饰变量 则该变量不能被重新赋值。因为该变量是常量。
- 修饰成员变量 同final修饰变量。
- 修饰引用类型 则引用类型的地址不能变,对象里面的内容可以变
抽象类
- 抽象方法:使用关键字abstract来修饰的方法,而且不含有方法体。
- 要求:抽象方法不能有方法体 即没有花括号包括花括号,直接在()后面加一个;就行。
抽象方法和空方法体 不是一个个概念;例如
抽象方法:public abstract void text();
空方法体:public void test(){}
-
抽象类:必须使用abstract修饰符来修饰,而且不能被实例化,即无法使用new关键字创建新的对象实例。主要用途是被子类继承调用。抽象类可以含有成员变量 方法(普通方法 ,抽象方法) ,构造器,初始化块,内部类(接口 ,枚举)5种成分,抽象类的构造器不能用于创建实例,含有抽象方法的类(包括直接定义一个抽象方法,或者继承了一个父类 但没有完全实现父类包含的方法,或者实现了一个接口,但没有完全实现接口包含的抽象方法)只能被定义成抽象类。
-
抽象类的子类 如果不重写父类方法 则子类仍是抽象类 如果重写父类的抽象方法,则子类为具体类 ,实现子类的方法靠 多态实现。
-
归纳:抽象类有得有失
- 得 :抽象类多了一个能力抽象类可以含有抽象方法
- 抽象类失去了一个能力,不能创建实例。
-
利用抽象类和抽象方法 可以很好的发挥多态的优势.
-
使用abstract修饰类 表明这个类只能被继承,修饰方法表明这个方法只能由子类重写(实现) 而final修饰类不能被继承 ,final修饰方法不能被重写。因此final和abstract永远不可能同时使用.
-
abstract 不能修饰变量 不能修饰构造器
-
static修饰方法是 表明属于类本身 即通过类调用方法 ,但是如果被定义为抽象方法,会导致使用类来调用该方法时出现错误。 因此static和abstract必能同时修饰一个方法。但是可以同时修饰一个内部类
-
abstract修饰的方法必须被子类重写才有意义,private修饰方法 不能被子类调用 就是说 abstract和private不能修饰同一个方法。
lambda表达式
引入匿名内部类知识:
/*
匿名内部类
就是内部类的简化写法。
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:
new 类名或者接口名(){
重写方法;
}
本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。
interface Inter {
public abstract void show();
public abstract void show2();
}
class Outer {
public void method() {
//一个方法的时候
/*
new Inter() {
public void show() {
System.out.println("show");
}
}.show();
*/
//二个方法的时候
/*
new Inter() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show();
new Inter() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show2();
*/
//匿名内部类引入
//如果我是很多个方法,就很麻烦了
//那么,我们有没有改进的方案呢?
Inter i = new Inter() { //多态
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
};
i.show();
i.show2();
}
}
class InnerClassDemo6 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
/*
匿名内部类在开发中的使用 (升级)
*/
interface Person {
public abstract void study();
}
class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}
//实现类 //被匿名内部类代替
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
代替原来实现接口类的类
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}
/*
匿名内部类在开发中的使用 (升级)
*/
interface Person {
public abstract void study();
}
class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}
//实现类 //被匿名内部类代替
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
代替原来实现接口类的类
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}
- 进入lambda表达式:
- 这个表达式和匿名内部类有相同的作用(都是用来代替实现接口类) 但是要比匿名内部类简单的多。
话不多说 看代码:
interface command
{
//接口里定义的process 方法用于封装“出路行为”
void process(int[] target);
}
public class ProcessArray
{
public void process(int[] target , command cmd)
{
cmd.process(target);
}
}
//这个是要被匿名内部类和lambda代替的东东
public class PrintCommand implaments Command
{
public void process(int[] target )
{
for(int tmp :target)
{
System.out.println("遍历"+tmp);
}
}
}
/*这是普通写*/
public class CommandTest
{
public static void main(Strint[] args)
{
ProcessArray pa = new ProcessArray();
int[] target = {3,-4,6,4};
pa.process(target , new PrintCommand());
}
}
/*这是匿名内部类写(代替实现接口的类)*/
public class CommandTest1
{
public static void main(Strint[] args)
{
ProcessArray pr = new ProcessArray();
int[] target = {3.-4.6.4};
pa.process(target , new Command())
{
public void process(int[] target)
{
for(int tmp : target)
{
System.out.println("遍历:"+tmp);
}
}
}
}
}
/*使用lambda表达式((终极版)仍然代替实现接口的类)*/
public class CommandTest2
{
public static void main(Strint[] args)
{
ProcessArray pr = new ProcessArray();
int[] array = {3.-4.6.4};
pa.process(array ,(int[] target)->{
for(int tmp : target)
{
System.out.println("遍历"+tmp);
}
});
}
}
- lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(函数式接口)
- 它由三部分组成
1.形参列表。允许省略形参类型。如果只有一个形参 也可以省略()
2.箭头 (->)。
3.代码块。 - lambda表达式和匿名内部类的联系:
- 联系:
- 都可以直接访问(默认final修饰)局部变量,以及外部类的成员变量 (实例变量和类变量)
- lambda创建的对象和匿名内部类生成的对象一样 都可以直接调用从接口中继承的默认方法
- 联系: