Java学习-t6-面向对象下

 

 

 

t6.2

6.2.1 字符串的== 判断:

		// s1直接引用常量池中的"疯狂Java"
		String s1 = "疯狂Java";
		String s2 = "疯狂";
		String s3 = "Java";
		// s4后面的字符串值可以在编译时就确定下来
		// s4直接引用常量池中的"疯狂Java"
		String s4 = "疯狂" + "Java";
		// s5后面的字符串值可以在编译时就确定下来
		// s5直接引用常量池中的"疯狂Java"
		String s5 = "疯" + "狂" + "Java";
		// s6后面的字符串值不能在编译时就确定下来,
		// 不能引用常量池中的字符串
		String s6 = s2 + s3;
		// 使用new调用构造器将会创建一个新的String对象,
		// s7引用堆内存中新创建的String对象
		String s7 = new String("疯狂Java");
		System.out.println(s1 == s4); // 输出true
		System.out.println(s1 == s5); // 输出true
		System.out.println(s1 == s6); // 输出false
		System.out.println(s1 == s7); // 输出false

6.2.2 两个对象相等判断:

package com.lee.test.ligang.unit6.t2;

class Person {
	private String name;
	private String idStr;

	public Person() {
	}

	public Person(String name, String idStr) {
		this.name = name;
		this.idStr = idStr;
	}

	// 此处省略name和idStr的setter和getter方法。
	// name的setter和getter方法
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	// idStr的setter和getter方法
	public void setIdStr(String idStr) {
		this.idStr = idStr;
	}

	public String getIdStr() {
		return this.idStr;
	}

	// 重写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())) {
				return true;
			}
		}
		return false;
	}
}

public class OverrideEqualsRight {
	public static void main(String[] args) {
		Person p1 = new Person("孙悟空", "12343433433");
		Person p2 = new Person("孙行者", "12343433433");
		Person p3 = new Person("孙悟饭", "99933433");
		// p1和p2的idStr相等,所以输出true
		System.out.println("p1和p2是否相等?" + p1.equals(p2));
		// p2和p3的idStr不相等,所以输出false
		System.out.println("p2和p3是否相等?" + p2.equals(p3));
	}
}

6.2.3 eqauls判断

		int it = 65;
		float fl = 65.0f;
		// 将输出true
		System.out.println("65和65.0f是否相等?" + (it == fl));
		char ch = 'A';
		// 将输出true
		System.out.println("65和'A'是否相等?" + (it == ch));
		String str1 = new String("hello");
		String str2 = new String("hello");
		// 将输出false
		System.out.println("str1和str2是否相等?" + (str1 == str2));
		// 将输出true
		System.out.println("str1是否equals str2?" + (str1.equals(str2)));
		// 由于java.lang.String与EqualTest类没有继承关系,
		// 所以下面语句导致编译错误
		// System.out.println("hello" == new EqualTest());

t6.3类成员

t6.4final修饰符

final成员变量

【规则】【6.4.1】final修饰的成员变量,可以申明不赋值,但必须在后面初始化快、静态代码块、构造方法中显示的赋值

 

【规则】宏变量的使用

import java.util.Arrays;

class Person {
	private int age;

	public Person() {
	}

	// 有参数的构造器
	public Person(int age) {
		this.age = age;
	}

	// 省略age的setter和getter方法
	// age的setter和getter方法
	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return this.age;
	}
}

public class FinalReferenceTest {
	public static void main(String[] args) {
		// final修饰数组变量,iArr是一个引用变量
		final int[] iArr = { 5, 6, 12, 9 };
		System.out.println(Arrays.toString(iArr));
		// 对数组元素进行排序,合法
		Arrays.sort(iArr);
		System.out.println(Arrays.toString(iArr));
		// 对数组元素赋值,合法
		iArr[2] = -8;
		System.out.println(Arrays.toString(iArr));
		// 下面语句对iArr重新赋值,非法
		// iArr = null;
		// final修饰Person变量,p是一个引用变量
		final Person p = new Person(45);
		// 改变Person对象的age实例变量,合法
		p.setAge(23);
		System.out.println(p.getAge());
		// 下面语句对p重新赋值,非法
		// p = null;
	}
}
		String s1 = "疯狂Java";
		// s2变量引用的字符串可以编译时就确定出来,
		// 因此s2直接引用常量池中已有的"疯狂Java"字符串
		String s2 = "疯狂" + "Java";
		System.out.println(s1 == s2);
		// 定义2个字符串直接量
		String str1 = "疯狂";     //①
		String str2 = "Java";     //②
		// 将str1和str2进行连接运算
		String s3 = str1 + str2;
		System.out.println(s1 == s3);

【规则】final方法的重写

//不可重写:
public class FinalMethodTest {
	public final void test() {
	}
}

class Sub extends FinalMethodTest {
	// 下面方法定义将出现编译错误,不能重写final方法
//	public void test() {
//	}
}
//可重写:

public class PrivateFinalMethodTest
{
	private final void test(){}
}
class Sub extends PrivateFinalMethodTest
{
	// 下面方法定义将不会出现问题
	public void test(){}
}

【规则】设计不可变类

class Name {
	private String firstName;
	private String lastName;

	public Name() {
	}

	public Name(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}

	// 省略firstName、lastName的setter和getter方法
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getFirstName() {
		return this.firstName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getLastName() {
		return this.lastName;
	}
}

public class Person {
	private final Name name;

	// 这种构造函数会破坏final设计初衷
	// public Person(Name name) {
	// this.name = name;
	// }

	// public Name getName() {
	// return name;
	// }

	public Person(Name name) {
		this.name = new Name(name.getFirstName(), name.getLastName());
	}

	public Name getName() {
		return new Name(name.getFirstName(), name.getLastName());
	}

	public static void main(String[] args) {
		Name n = new Name("悟空", "孙");
		Person p = new Person(n);
		// Person对象的name的firstName值为"悟空"
		System.out.println(p.getName().getFirstName());
		// 改变Person对象name的firstName值
		n.setFirstName("八戒");
		// Person对象的name的firstName值被改为"八戒"
		System.out.println(p.getName().getFirstName());
	}
}

【模式】缓存实例的不可变类

class CacheImmutale
{
	private static int MAX_SIZE = 10;
	// 使用数组来缓存已有的实例
	private static CacheImmutale[] cache
		= new CacheImmutale[MAX_SIZE];
	// 记录缓存实例在缓存中的位置,cache[pos-1]是最新缓存的实例
	private static int pos = 0;
	private final String name;
	private CacheImmutale(String name)
	{
		this.name = name;
	}
	public String getName()
	{
		return name;
	}
	public static CacheImmutale valueOf(String name)
	{
		// 遍历已缓存的对象,
		for (int i = 0 ; i < MAX_SIZE; i++)
		{
			// 如果已有相同实例,直接返回该缓存的实例
			if (cache[i] != null
				&& cache[i].getName().equals(name))
			{
				return cache[i];
			}
		}
		// 如果缓存池已满
		if (pos == MAX_SIZE)
		{
			// 把缓存的第一个对象覆盖,即把刚刚生成的对象放在缓存池的最开始位置。
			cache[0] = new CacheImmutale(name);
			// 把pos设为1
			pos = 1;
		}
		else
		{
			// 把新创建的对象缓存起来,pos加1
			cache[pos++] = new CacheImmutale(name);
		}
		return cache[pos - 1];

	}
	public boolean equals(Object obj)
	{
		if(this == obj)
		{
			return true;
		}
		if (obj != null && obj.getClass() == CacheImmutale.class)
		{
			CacheImmutale ci = (CacheImmutale)obj;
			return name.equals(ci.getName());
		}
		return false;
	}
	public int hashCode()
	{
		return name.hashCode();
	}
}
public class CacheImmutaleTest
{
	public static void main(String[] args)
	{
		CacheImmutale c1 = CacheImmutale.valueOf("hello");
		CacheImmutale c2 = CacheImmutale.valueOf("hello");
		// 下面代码将输出true
		System.out.println(c1 == c2);
	}
}

【规则】Integer的缓存策略

		// 生成新的Integer对象
		Integer in1 = new Integer(6);
		// 生成新的Integer对象,并缓存该对象
		Integer in2 = Integer.valueOf(6);
		// 直接从缓存中取出Ineger对象
		Integer in3 = Integer.valueOf(6);
		System.out.println(in1 == in2); // 输出false
		System.out.println(in2 == in3); // 输出true
		// 由于Integer只缓存-128~127之间的值,
		// 因此200对应的Integer对象没有被缓存。
		Integer in4 = Integer.valueOf(200);
		Integer in5 = Integer.valueOf(200);
		System.out.println(in4 == in5); //输出false

t6.7 内部类

t6.7.1 非静态内部类

package com.lee.test.ligang.unit6.t7.t1;

public class Cow {
	private double weight;

	// 外部类的两个重载的构造器
	public Cow() {
	}

	public Cow(double weight) {
		this.weight = weight;
	}

	// 定义一个非静态内部类
	private class CowLeg {
		// 非静态内部类的两个实例变量
		private double length;
		private String color;

		// 非静态内部类的两个重载的构造器
		public CowLeg() {
		}

		public CowLeg(double length, String color) {
			this.length = length;
			this.color = color;
		}

		// 下面省略length、color的setter和getter方法
		public void setLength(double length) {
			this.length = length;
		}

		public double getLength() {
			return this.length;
		}

		public void setColor(String color) {
			this.color = color;
		}

		public String getColor() {
			return this.color;
		}

		// 非静态内部类的实例方法
		public void info() {
			System.out.println("当前牛腿颜色是:" + color + ", 高:" + length);
			// 直接访问外部类的private修饰的成员变量
			System.out.println("本牛腿所在奶牛重:" + weight); // ①
		}
	}

	public void test() {
		CowLeg cl = new CowLeg(1.12, "黑白相间");
		cl.info();
	}

	public static void main(String[] args) {
		Cow cow = new Cow(378.9);
		cow.test();
	}
}

package com.lee.test.ligang.unit6.t7.t1;

public class DiscernVariable {
	private String prop = "外部类的实例变量";

	private class InClass {
		private String prop = "内部类的实例变量";

		public void info() {
			String prop = "局部变量";
			// 通过 外部类类名.this.varName 访问外部类实例变量
			System.out.println("外部类的实例变量值:" + DiscernVariable.this.prop);
			// 通过 this.varName 访问内部类实例的变量
			System.out.println("内部类的实例变量值:" + this.prop);
			// 直接访问局部变量
			System.out.println("局部变量的值:" + prop);
		}
	}

	public void test() {
		InClass in = new InClass();
		in.info();
	}

	public static void main(String[] args) {
		new DiscernVariable().test();
	}
}

package com.lee.test.ligang.unit6.t7.t1;

public class Outer {
	private int outProp = 9;

	class Inner {
		private int inProp = 5;

		public void acessOuterProp() {
			// 非静态内部类可以直接访问外部类的private成员变量
			System.out.println("外部类的outProp值:" + outProp);
		}
	}

	public void accessInnerProp() {
		// 外部类不能直接访问非静态内部类的实例变量,
		// 下面代码出现编译错误
		// System.out.println("内部类的inProp值:" + inProp);
		// 如需访问内部类的实例变量,必须显式创建内部类对象
		System.out.println("内部类的inProp值:" + new Inner().inProp);
	}

	public static void main(String[] args) {
		// 执行下面代码,只创建了外部类对象,还未创建内部类对象
		Outer out = new Outer(); // ①
		out.accessInnerProp();
	}
}

t.6.7.2静态内部类

package com.lee.test.ligang.unit6.t7.t2;

public class StaticInnerClassTest {
	private int prop1 = 5;
	private static int prop2 = 9;

	static class StaticInnerClass {
		// 静态内部类里可以包含静态成员
		private static int age;

		public void accessOuterProp() {
			// 下面代码出现错误:
			// 静态内部类无法访问外部类的实例变量
//			System.out.println(prop1);
			// 下面代码正常
			System.out.println(prop2);
		}
	}
}

package com.lee.test.ligang.unit6.t7.t2;
public class AccessStaticInnerClass
{
	static class StaticInnerClass
	{
		private static int prop1 = 5;
		private int prop2 = 9;
	}
	public void accessInnerProp()
	{
		// System.out.println(prop1);
		// 上面代码出现错误,应改为如下形式:
		// 通过类名访问静态内部类的类成员
		System.out.println(StaticInnerClass.prop1);
		// System.out.println(prop2);
		// 上面代码出现错误,应改为如下形式:
		// 通过实例访问静态内部类的实例成员
		System.out.println(new StaticInnerClass().prop2);
	}
}

t6.7.3内部类使用规则

package com.lee.test.ligang.unit6.t7.t3;

class Out {
	// 定义一个内部类,不使用访问控制符,
	// 即只有同一个包中其他类可访问该内部类
	class In {
		public In(String msg) {
			System.out.println(msg);
		}
	}
}

public class CreateInnerInstance {
	public static void main(String[] args) {
		Out.In in = new Out().new In("测试信息");
		/*
		 * 上面代码可改为如下三行代码: 使用OutterClass.InnerClass的形式定义内部类变量 Out.In in;
		 * 创建外部类实例,非静态内部类实例将寄存在该实例中 Out out = new Out();
		 * 通过外部类实例和new来调用内部类构造器创建非静态内部类实例 in = out.new In("测试信息");
		 */
	}
}

package com.lee.test.ligang.unit6.t7.t3;

class StaticOut {
	// 定义一个静态内部类,不使用访问控制符,
	// 即同一个包中其他类可访问该内部类
	static class StaticIn {
		public StaticIn() {
			System.out.println("静态内部类的构造器");
		}
	}
}

public class CreateStaticInnerInstance {
	public static void main(String[] args) {
		StaticOut.StaticIn in = new StaticOut.StaticIn();
		/*
		 * 上面代码可改为如下两行代码: 使用OutterClass.InnerClass的形式定义内部类变量 StaticOut.StaticIn
		 * in; 通过new来调用内部类构造器创建静态内部类实例 in = new StaticOut.StaticIn();
		 */
	}
}


package com.lee.test.ligang.unit6.t7.t3;

public class SubClass extends Out.In {
	// 显示定义SubClass的构造器
	public SubClass(Out out) {
		// 通过传入的Out对象显式调用In的构造器
		out.super("hello");
	}
}

t6.8 Lambda表达式

t6.8.1 Lambda入门

package com.lee.test.ligang.unit6.t8.t1;
public interface Command
{
	// 接口里定义的process()方法用于封装“处理行为”
	void process(int[] target);
}

package com.lee.test.ligang.unit6.t8.t1;

public class CommandTest {
	public static void main(String[] args) {
		ProcessArray pa = new ProcessArray();
		int[] array = { 3, -4, 6, 4 };
		// 处理数组,具体处理行为取决于匿名内部类
		pa.process(array, new Command() {
			public void process(int[] target) {
				int sum = 0;
				for (int tmp : target) {
					sum += tmp;
				}
				System.out.println("数组元素的总和是:" + sum);
			}
		});
	}
}

package com.lee.test.ligang.unit6.t8.t1;
public class CommandTest2
{
	public static void main(String[] args)
	{
		ProcessArray pa = new ProcessArray();
		int[] array = {3, -4, 6, 4};
		// 处理数组,具体处理行为取决于匿名内部类,可以简写类型
//		pa.process(array , (int[] target)->{
		pa.process(array , target->{
				int sum = 0;
				for (int tmp : target )
				{
					sum += tmp;
				}
				System.out.println("数组元素的总和是:" + sum);
			});
	}
}

package com.lee.test.ligang.unit6.t8.t1;

interface Eatable {
	void taste();
}

interface Flyable {
	void fly(String weather);
	default void fly2(String weather){
		System.out.println("今天天气是:" + weather);
		System.out.println("直升机飞行平稳");
	}
}

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) {
		LambdaQs lq = new LambdaQs();
		// Lambda表达式的代码块只有一条语句,可以省略花括号。
		lq.eat(() -> System.out.println("苹果的味道不错!"));
		// Lambda表达式的形参列表只有一个形参,省略圆括号【形参根据接口类型自定义申明变量名】
		lq.drive(weather -> {
			System.out.println("今天天气是:" + weather);
			System.out.println("直升机飞行平稳");
		});
		new Flyable() {
			@Override
			public void fly(String weather) {
				
			}
		}.fly2("【碧空如洗的晴日】");;
		// Lambda表达式的代码块只有一条语句,省略花括号
		// 代码块中只有一条语句,即使该表达式需要返回值,也可以省略return关键字。
		lq.test((a, b) -> a + b);
	}
}

package com.lee.test.ligang.unit6.t8.t1;
public class ProcessArray
{
	public void process(int[] target , Command cmd)
	{
		cmd.process(target);
	}
}

t6.8.2 Lambda表达式与接口

java.util.function 大量函数式接口:

XxxFunction:

   return apply();

XxxConsumer:

   void accept();

XxxPredicate:

   Boolean test();

XxxSupplier:

    return getAsXxx();

 

 

 

package com.lee.test.ligang.unit6.t8.t2;

@FunctionalInterface
interface FkTest {
	void run();
}

public class LambdaTest {
	public static void main(String[] args) {
		// Runnable接口中只包含一个无参数的方法
		// Lambda表达式代表的匿名方法实现了Runnable接口中唯一的、无参数的方法
		// 因此下面的Lambda表达式创建了一个Runnable对象
		Runnable r = () -> {
			for (int i = 0; i < 100; i++) {
				System.out.println();
			}
		};
		// // 下面代码报错: 不兼容的类型: Object不是函数接口
		// Object obj = () -> {
		// for(int i = 0 ; i < 100 ; i ++)
		// {
		// System.out.println();
		// }
		// };

		Object obj1 = (Runnable) () -> {
			for (int i = 0; i < 100; i++) {
				System.out.println();
			}
		};

		// 同样的Lambda表达式可以被当成不同的目标类型,唯一的要求是:
		// Lambda表达式的形参列表与函数式接口中唯一的抽象方法的形参列表相同
		Object obj2 = (FkTest) () -> {
			for (int i = 0; i < 100; i++) {
				System.out.println();
			}
		};

	}
}

 

t.6.8.3 方法引用与构造器引用

 

 

 

1.接口中的方法

    1.1有实现
        必须显式修饰static

1.2无实现

你可能感兴趣的:(Java学习-t6-面向对象下)