java面向对象(下)

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创建的对象和匿名内部类生成的对象一样 都可以直接调用从接口中继承的默认方法

你可能感兴趣的:(编程语言,java思想)