java 06
java 06封装多态抽象类和接口抽象方法和抽象类接口interface字符串String类API文档如何阅读String类常用方法内部类成员内部类非静态内部类静态内部类匿名内部类局部内部类
封装
-
理念:高内聚,低耦合
-
优点:
-
提高代码的安全性。
-
提高代码的复用性
-
高内聚:封装细节,便于修改内部代码,提高可维护性
-
低耦合:简化外部调用,便于调用者使用,便于扩展和实现
-
实现:使用访问控制符
修饰符 | 同一类中 | 同一个包中 | 子类 | 所有类 |
---|---|---|---|---|
private | yes | |||
default | yes | yes | ||
protected | yes | yes | yes | |
public | yes | yes | yes | yes |
-
关于protected的两个细节:
-
若子类和父类在同一个包中,子类可以访问父类的protected成员,也可访问父类对象的protected的成员
-
若子类和父类不在同一包中,子类可以访问父类的protected成员,不能访问父类对象的protected的成员
-
关于封装中的简单原则:属性一般使用private访问权限;一些用于本类的辅助方法可以用private修饰,希望其他类调用的方法用public修饰
package a; public class Person { private int testPrivate; int testDefault; protected int testProtected; public int testPublic; public void test(){ System.out.println(this.testPrivate); } } public class Student extends Person{ public void study(){ System.out.println(super.testDefault); Person p = new Person(); //System.out.println(p.testPrivate);//不能访问 System.out.println(p.testDefault); System.out.println(p.testProtected); } }
package b; public class Boy extends Person { public void play(){ System.out.println(this.testProtected); System.out.println(super.testPublic); Person p = new Person(); //子类不能访问父类对象的成员 //System.out.println(p.testProtected); } } public class TestUser { private int id; private String name; private boolean man; public void printUserInfo(){ System.out.println(id); System.out.println(name); System.out.println(man); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isMan() { return man; } public void setMan(boolean man) { this.man = man; } } public class TestUserTest { public static void main(String[] args) { TestUser u = new TestUser(); u.setId(100); u.setName("xy"); u.setMan(false); System.out.println(u.getName()); System.out.println(u.isMan()); System.out.println(); } }
多态
-
同一个方法调用不同对象行为完全不同
-
要点: 1. 方法的多态,不是属性的多态
2. 三个必要条件:继承、方法重写、父类引用指向子类对象、 3. 父类引用指向子类对象后,用该父类引用调用子类重写方法,此时就实现多态
-
Animal animal = new Dog();//编译时类型Animal 运行时类型Dog
-
对象的转型:
- 向上转型:父类引用指向子类对象(自动) - 向下转型:向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时类型的方法。这时。我们就需要进行类型的强制转换,我们称之为向下转型
public class Animal { public void shout(){ System.out.println("叫了一声"); } } class Dog extends Animal{ public void shout(){ System.out.println("wang wang wang"); } public void seeDoor(){ System.out.println("see door"); } } class Cat extends Animal{ @Override public void shout() { System.out.println("miao miao miao"); } public void catchMouse(){ System.out.println("catch Mouse"); } } //测试多态 public class TestAnimal { public static void main(String[] args) { // animalCry(new Dog()); // animalCry(new Cat()); Animal animal = new Dog();//向上转型(自动) animal.shout(); Dog d = (Dog)animal;//向下转型(强制) //animal和d是同一个对象 d.seeDoor(); // animal.seeDoor();//编译错误 //Cat c = (Cat) animal;编译不会曝错,运行会曝错 if (animal instanceof Cat){ Cat c = (Cat) animal; c.catchMouse(); } } static void animalCry(Animal a){//Animal a = new Dog(); System.out.println("TestAnimal.animalCry"); a.shout();// } }
抽象类和接口
抽象方法和抽象类
-
抽象方法: 1. 使用abstract修饰的方法,没有方法体,只有方法声明
-
定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现
-
-
抽象类:包含抽象方法的类就是抽象类,通过抽象类,我们就可以严格限制子类的设计,使子类之间更加通用
-
使用要点:
-
有抽象方法的类只能定义抽象类
-
抽象类不能实例化,即不能用new来实例化抽象类
-
抽象类可以包含属性、方法、构造方法、但是构造方法不能用来new实例,只能被子类调用
-
抽象类只能用来被继承
-
抽象方法必须被子类实现
//测试抽象类 public abstract class Animal { int age; public abstract void rest(); public abstract void run(); public void shout(){ System.out.println("Animal.shout"); } } class Dog extends Animal{ @Override public void rest() { System.out.println("Dog.rest"); } @Override public void run() { System.out.println("Dog.run"); } } class Cat extends Animal{ @Override public void rest() { System.out.println("Cat.rest"); } @Override public void run() { System.out.println("Cat.run"); } }
接口interface
-
接口是一组规范,所有实现类都要遵守
-
接口和实现类不是父子关系,是实现规则关系
-
接口中的属性只能是常量。public static final 修饰
-
接口的方法只能是public abstract
-
子类通过implements 来实现接口中的规范、
-
接口不能创建实例,但是可以声明引用对象的类型
-
一个类实现了接口,必须实现接口中的所有方法,并且这些方法只能是public
-
接口中定义静态方法和默认方法(JDK8) - java 8 之前,接口里的方法要求全部是抽象方法。 - java 8 之后,允许在接口里定义默认方法和静态方法 - java 8 之后,我们可以在接口中直接定义静态方法的实现。这个静态方法直接从属于接口,可以通过接口名调用
-
注:默认方法可以调用静态方法;静态方法不可调用morenfangfa
-
接口的多继承:子接口extends负借口,会获得父接口的一切
//飞行接口 public interface Fly { /*public static final*/int FLY_HEIGHT = 100; /*public abstract*/void fly(); } //善良接口 interface Honest{ void HelpOther(); } class GoodMan implements Honest{ @Override public void HelpOther() { System.out.println("扶老奶奶过马路"); } } class BirdMan implements Fly{ @Override public void fly() { System.out.println("fei fei fei"); } } class Angel implements Fly,Honest{ @Override public void fly() { System.out.println("Angel.fly"); } @Override public void HelpOther() { System.out.println("Angel.HelpOther"); } } class Plane implements Fly{ @Override public void fly() { } } //测试接口中的新特性-默认方法和静态方法 public interface TestDefault { void printInfo(); default void moren(){//接口里的一个默认方法 System.out.println("TestDefault.moren"); System.out.println("测试默认方法"); testStatic01();//默认方法可以调用静态方法 } static void testStatic01(){ System.out.println("TestDefault.testStatic01"); } } class TestDefaultImpl01 implements TestDefault{ @Override public void printInfo() { } static void testStatic01(){ System.out.println("TestDefaultImpl01.testStatic01"); } } public class Test { public static void main(String[] args) { Angel a = new Angel(); a.fly(); a.HelpOther(); System.out.println(Fly.FLY_HEIGHT); Fly a1 = new Angel();//多态 a1.fly(); System.out.println("============测试默认方法========"); TestDefault td = new TestDefaultImpl01(); td.printInfo(); td.moren(); System.out.println("============测试静态方法========"); TestDefault.testStatic01(); TestDefaultImpl01.testStatic01(); } }
//测试接口的多继承 public class TestMultipleInterface { public static void main(String[] args) { C c = new CImpl01(); c.testC(); c.testB(); c.testA(); } } interface A{ void testA(); } interface B{ void testB(); } interface C extends A,B{ void testC(); } class CImpl01 implements C{ @Override public void testA() { System.out.println("CImpl01.testA"); } @Override public void testB() { System.out.println("CImpl01.testB"); } @Override public void testC() { System.out.println("CImpl01.testC"); } }
字符串String类
-
String类又称作不可变字符序列
-
String位于java.lang包中,java程序默认导入java.lang包中的多有类
-
java字符串是Unicode字符序列
-
java没有内置字符串类型,每个用双引号括起来的字符串都是String类的一个实例
-
String类和常量池 - 常量池分为三种:全局字符串常量池,class文件常量池,运行时常量池 - 每一个class都有一个运行时常量池
API文档如何阅读
-
下载--解压--docs -- api -- index.html
String类常用方法
public class StringTest01 { public static void main(String[] args) { String s1 = "core java"; String s2 = "Core java"; System.out.println(s1.charAt(3));//提取下标为3的字符 System.out.println(s2.length());//字符串的长度 System.out.println(s1.equals(s2));//比较两个字符串是否相等 System.out.println(s1.equalsIgnoreCase(s2));// 比较两个字符串(忽略大小写) System.out.println(s1.indexOf("java"));//字符串s1中是否包含java System.out.println(s1.indexOf("apple"));//字符串s1中是否包含apple String s3 = "I love java. java is the best language!"; System.out.println(s3.indexOf("java")); System.out.println(s3.lastIndexOf("java")); String s = s1.replace(' ','&');//将s1中的空格替换成& System.out.println("result:"+s); } } import java.util.Locale; public class StringTest02 { public static void main(String[] args) { String s = ""; String s1 = "How are you?"; System.out.println(s1.startsWith("How"));//是否以How开头 System.out.println(s1.endsWith("you"));//是否以you结尾 s = s1.substring(4);//提取子字符串:从下标为4的开始到字符串结尾为止 System.out.println(s); s = s1.substring(4,7);//提取子字符串下标【4,7) 不包括7 System.out.println(s); s = s1.toLowerCase(Locale.ROOT);//转小写 System.out.println(s); s = s1.toUpperCase(Locale.ROOT);//转大写 System.out.println(s); String s2 = " How old you!! "; s = s2.trim();//去除字符串首尾的空格。注意:中间空格不能去除 System.out.println(s); System.out.println(s2);//因为String是不可变字符串,所以s2不变 } } //测试字符串 public class TestString { public static void main(String[] args) { String s0 = null;//空 String s1 = "";//空字符串 String s2 = "java"; String s3 = new String("java"); System.out.println(s1.length()); System.out.println(s2.length()); //System.out.println(s0.length());//会爆出空指针异常 System.out.println("===========字符串相当问题=========="); String g1 = "上学堂"; String g2 = "上学堂"; String g3 = new String("上学堂"); System.out.println(g1==g2);//true System.out.println(g1==g3);//false System.out.println(g1.equals(g3));//true } }
内部类
-
我们把一个类放在另一个类的内部定义,称为内部类
-
内部类的访问:
-
外部类中定义内部类:new Inner();
-
外部类以外的地方使用静态内部类:Outer.Inner varname = new Outer().new Inner();
-
//测试内部类的用法 public class Outer { private int age=10; public void show(){ System.out.println("Outer.show"); System.out.println(age); } //定义内部类 public class Inner{ int age = 20; public void show(){ System.out.println("Inner.show"); System.out.println(age); System.out.println(Outer.this.age); Outer.this.show(); } } } public class TestInner { public static void main(String[] args) { Outer.Inner inner = new Outer().new Inner(); inner.show(); } }
成员内部类
-
要点:
-
内部类提供了更好的封装。只能让外部类直接访问。不允许同一个包中的其他类直接访问
-
内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。但外部类不能直接访问内部类的内部属性
-
访问内部类属性:this.变量名
-
访问外部类属性:外部类名.this.变量名
非静态内部类
-
非静态内部类对象必须寄存在一个外部类对象里
-
非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类的成员
-
非静态内部类不能有静态方法,静态属性和静态初始化块
静态内部类
-
使用要点: - 静态内部类可以访问外部类的静态成员,不能访问外部类的普通成员 - 静态内部类看做外部类的一个静态成员
//测试静态内部类 class Outer2 { private int a = 10; private static int b = 20; //相当于外部类的一个静态成员 static class Inner2{ public void test(){ //System.out.println(a);//静态内部类不能访问外部类的普通属性 System.out.println(b);//静态内部类可以访问外部类的静态属性 } } } class TestStaticInnerClass{ public static void main(String[] args) { //通过new外部类名.内部类名() 来创建内部类对象 Outer2.Inner2 inner = new Outer2.Inner2(); inner.test(); } public void test1(A 第一个匿名内部类) { } }
匿名内部类
-
适合某种只需要使用一次的类
//测试匿名内部类 public class TestAnonymousInnerClass { public void test1(A a){ a.run(); } public static void main(String[] args) { TestStaticInnerClass t = new TestStaticInnerClass(); t.test1(new A() { @Override public void run() { System.out.println("第一个匿名内部类"); } }); t.test1(new A() { @Override public void run() { System.out.println("第二个匿名内部类"); } }); } } interface A{ void run(); }
局部内部类
-
仅限于该方法
//测试局部内部类 public class TestLocalInnerClass { public void show(){ //作用域仅限于该方法 class Inner3{ public void fun(){ System.out.println("hello world"); } } new Inner3().fun(); } public static void main(String[] args) { new TestLocalInnerClass().show(); } }