文章目录
- 5.1.1 l类的继承
- 5.1.2 instanceof 运算符
- 5.1.4方法的重写override
- 5.2.1 Object类基本特性
- 5.2.2 toString方法
- 5.2.3 ==和equals方法
- 5.3 super关键字
- 5.4.2 封装的实现—使用访问控制符
- 修饰符范围限制
- 5.4.3 封装的使用细节
- 5.4.3 封装的使用细节
- 5.5 多态(polymorphism)
- 5.7 final关键字
- 5.8 抽象方法和抽象类(abstract)
- 5.9.2 如何定义和使用接口? (interface)
- 5.9.3 接口的多继承
- 5.10.2内部类的分类
- 5.11.3阅读API文档
- 5.11.4 String类常用的方法
- xxx
- 课后部分习题
5.1.1 l类的继承
注意点
- 关键字 extends
Java只有单继承(c++有多)
- 父类又称 超类、基类、派生等
子类可以继承父类所有的属性和方法(父类 的构造方法除外)
但不一定都可以直接调用(父类私有属性方法private修饰)
- 定义一个类时,没有调用extends,则它的父类是:java.lang.Object。
public class Test{
public static void main(String[] args) {
Student s = new Student("高淇",172,"Java");
s.rest();
s.study();
}
}
class Person {
String name;
int height;
public void rest(){
System.out.println("休息一会!");
}
}
class Student extends Person {
String major; //专业
public void study(){
System.out.println("在尚学堂,学习Java");
}
public Student(String name,int height,String major) {
//天然拥有父类的属性
this.name = name;
this.height = height;
this.major = major;
}
}
5.1.2 instanceof 运算符
- instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回true;否则,返回false。比如:
public class Test{
public static void main(String[] args) {
Student s = new Student("高淇",172,"Java");
System.out.println(s instanceof Person);
System.out.println(s instanceof Student);
}
}
PS:查看类的继承结构 Ctrl + T
5.1.4方法的重写override
就是在子类中写一个和父类方法名一样的 方法 调用子类此方法的时候用的是子类的…
注意点
-
“==”: 方法名、形参列表相同。
-
“≤”:返回值类型和声明异常类型,子类小于等于父类。
-
“≥”: 访问权限,子类大于等于父类。
5.2.1 Object类基本特性
- Object类是Java的根基类,所Java都拥有它的属性和方法 如果在类的声明中没有使用extends继承父类
则默认继承Object类
5.2.2 toString方法
class Person {
String name;
int age;
@Override
public String toString() {
return name+",年龄:"+age;
}
}
public class Test {
public static void main(String[] args) {
Person p=new Person();
p.age=20;
p.name="李东";
System.out.println("info:"+p);
Test t = new Test();
System.out.println(t);
}
}
5.2.3 ==和equals方法
- “==” : 代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。
- " equals": 表示两个对象内容是否相同
public class Test {
public static void main(String[] args) {
Person p1 = new Person(123,"高淇");
Person p2 = new Person(123,"高小七");
System.out.println(p1==p2); //false,不是同一个对象
System.out.println(p1.equals(p2)); //true,id相同则认为两个对象内容相同
String s1 = new String("尚学堂");
String s2 = new String("尚学堂");
System.out.println(s1==s1); //false, 两个字符串是同一个对象
System.out.println(s1.equals(s2)); //true, 两个字符串内容相同
}
}
class Person {
int id;
String name;
public Person(int id,String name) {
this.id=id;
this.name=name;
}
}
/*结果
false
false
true
true
*/
5.3 super关键字
- super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。
- 每一个继承父类的子类默认都会调用一下 super() 父类无参的构造方法;
当加上super.父类中方法名时调用的是所继承的父类的方法
public class TestSuper01 {
public static void main(String[] args) {
new ChildClass().f();
}
}
class FatherClass {
public int value;
public void f(){
value = 100;
System.out.println ("FatherClass.value="+value);
}
}
class ChildClass extends FatherClass {
public int value;
public void f() {
super.f(); //调用父类对象的普通方法
value = 200;
System.out.println("ChildClass.value="+value);
System.out.println(value);
System.out.println(super.value); //调用父类对象的成员变量
}
}
5.4.2 封装的实现—使用访问控制符
修饰符范围限制
- private 只能在同一个类中
- default(缺省的修饰符 )同一个包中都可以
- protected 不同包中的子类也可以(同一包下可以)
- public 所有包中的,所有类都可以
5.4.3 封装的使用细节
封装就是将一个对象的属性和操作进行整合处理
简单点说就是利用一个函数 用户只能通过这个 函数进行 操作
- 封装可以实现 数据 可控
- 可以减少后期 代码更改的工作量
再比如说,如果哪天我们需要将Person类中的age属性修改为String类型的,
你会怎么办?你只有一处使用了这个类的话那还比较幸运,但如果你有几十
处甚至上百处都用到了,那你岂不是要改到崩溃。而封装恰恰能解决这样的
问题。如果使用封装,我们只需要稍微修改下Person类的setAge()方法即可,
而无需修改使用了该类的客户代码。
5.4.3 封装的使用细节
- 目前我们一般用 private 修饰属性(进可以自身类内调用)
- 对于属性 使用get/set 方法进行封装(public)
- boolean 类型的属性 get 要用 is
- 一些用于本类中的辅助放方法用 private 修饰 用于他类的 用public
public class Person {
// 属性一般使用private修饰
private String name;
private int age;
private boolean flag;
// 为属性提供public修饰的set/get方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isFlag() {// 注意:boolean类型的属性get方法是is开头的
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
5.5 多态(polymorphism)
前提条件
- 多态是方法的多态,不是属性的多态(多态与属性无关)。
- 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
- 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
就是 写一个 用父类的方法 从中会自动选择 哪一个类型
个人理解:感觉就是 开了一个引用父类类型的 方法 从而 对这个方法进行调用是 由于 其子类(dog/cat)都
继承于 父类所以 会形成 父类方法的重载 其 中(dog/cat/animal)作为 不同类型的参数
class Animal {
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal {
public void shout() {
System.out.println("旺旺旺!");
}
public void seeDoor() {
System.out.println("看门中....");
}
}
class Cat extends Animal {
public void shout() {
System.out.println("喵喵喵喵!");
}
}
public class TestPolym {
public static void main(String[] args) {
Animal a1 = new Cat(); // 向上可以自动转型
//传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
animalCry(a1);
Animal a2 = new Dog();
animalCry(a2);//a2为编译类型,Dog对象才是运行时类型。
//编写程序时,如果想调用运行时类型的方法,只能进行强制类型转换。
// 否则通不过编译器的检查。
Dog dog = (Dog)a2;//向下需要强制类型转换
dog.seeDoor();
}
// 有了多态,只需要让增加的这个类继承Animal类就可以了。
static void animalCry(Animal a) {
a.shout();
}
/* 如果没有多态,我们这里需要写很多重载的方法。
* 每增加一种动物,就需要重载一种动物的喊叫方法。非常麻烦。
static void animalCry(Dog d) {
d.shout();
}
static void animalCry(Cat c) {
c.shout();
}*/
}
5.7 final关键字
- 修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
final int MAX_SPEED = 120;
- 修饰方法:该方法不可被子类重写。但是可以被重载!
final void study(){}
- 修饰类: 修饰的类不能被继承。比如:Math、String等。
5.8 抽象方法和抽象类(abstract)
** 使用abstract修饰的方法,没有方法体,只有声明。定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现。**
- 有抽象方法的类 必须定义成抽象类
- 抽象类不能被具体化(即不能用new来创建) 只能被子类调用
- 抽象类只能被继承
- 抽象方法必须被 子类实现
- (抽象类中只有抽象方法的声明,抽象方法写在继承他的子类中(非抽象),
- 子类中必须写抽象方法否则报错)
- 可以new子类因为只是继承而非 abstract类
package _01_java入门阶段;
public class Test {
//测试抽象类
public static void main(String[] args) {
Dog a = new Dog();
a.shout();
a.seeDoor();
}
}
abstract class Animal {
abstract public void shout(); //抽象方法
}
class Dog extends Animal {
//子类必须实现父类的抽象方法,否则编译错误
public void shout() {
System.out.println("汪汪汪!");
}
public void seeDoor(){
System.out.println("看门中....");
}
}
class Cat extends Animal{
public void shout() {
System.out.println("喵喵~");
}
}
5.9.2 如何定义和使用接口? (interface)
声明格式: interface 同类同级
[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] {
常量定义;
方法定义;
}
- 访问修饰符:只能是public或默认。
- 接口名:和类名采用相同命名机制。
- extends:接口可以多继承。
- 常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
- 方法:接口中的方法只能是:public abstract。 省略的话,也是public abstract。
几个特性 - 子类通过implements来实现接口中的规范。
- 接口不能创建实例,但是可用于声明引用变量类型。
- 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
- JDK1.7之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
- JDK1.8后,接口中包含普通的静态方法。
public class TestInterface {
public static void main(String[] args) {
Volant volant = new Angel();//不能调用 Angel中的 helpOther();
//Angel volant= new Angel(); //就可以调用 helpOther();
volant.fly();
System.out.println(Volant.FLY_HIGHT);
Honest honest = new GoodMan();
honest.helpOther();
}
}
/**飞行接口*/
interface Volant {
int FLY_HIGHT = 100; // 总是:public static final类型的;
void fly(); //总是:public abstract void fly();
}
/**善良接口*/
interface Honest {
void helpOther();
}
/**Angle类实现飞行接口和善良接口*/
class Angel implements Volant, Honest{
public void fly() {
System.out.println("我是天使,飞起来啦!");
}
public void helpOther() {
System.out.println("扶老奶奶过马路!");
}
}
class GoodMan implements Honest {
public void helpOther() {
System.out.println("扶老奶奶过马路!");
}
}
class BirdMan implements Volant {
public void fly() {
System.out.println("我是鸟人,正在飞!");
}
}
5.9.3 接口的多继承
interface A {
void testa();
}
interface B {
void testb();
}
/**接口可以多继承:接口C继承接口A和B*/
interface C extends A, B {
void testc();
}
public class Test implements C {
public void testc() {
}
public void testa() {
}
public void testb() {
}
}
5.10.2内部类的分类
- 成员内部类(非静态 、 静态)
- 匿名内部类
- 局部内部类
非静态成员内部类
- 非静态成员内部类必须定义外部类的对象里
- 非静态内部类可以直接访问 外部类成员,但是外部不能直接访问内部
- 非静态成员内部类不能定义 静态属性方法初始化块等
- 静态外部类静态方法、代码块不能访问非静态内部类也不能使用它定义变量、创建实例
成员变量访问要点:
5. 内部类里方法的局部变量:变量名。
6. 内部类属性:this.变量名。
7. 外部类属性:外部类名.this.变量名。
1.外部类中定义内部类:
new Inner()
2.外部类以外的地方使用非静态内部类:
Outer.Inner varname = new Outer().new Inner()
package _01_java入门阶段;
public class Test {
public static void main(String[] args) {
//先创建外部类实例,然后使用该外部类实例创建内部类实例
Outer.Inner inner =new Outer().new Inner();
inner.show();//一起创建
Outer outer = new Outer();//分步创建
Outer.Inner inn = outer.new Inner();
inn.show();
}
}
class Outer {
private int age = 10;
class Inner {
int age = 20;
public void show() {
int age = 30;
System.out.println("内部类方法里的局部变量age:" + age);// 30
System.out.println("内部类的成员变量age:" + this.age);// 20
System.out.println("外部类的成员变量age:" + Outer.this.age);// 10
}
}
}
静态内部类*
- 当一个静态内部类对象存在,并不一定存在对应的外部类对象。 因此,静态内部类的实例方法不能直接访问外部类的实例方法。
- 静态内部类看做外部类的一个静态成员。 因此,外部类的方法中可以通过:“静态内部类.名字”的方式访问静态内部类的静态成员,通过 new 静态内部类()访问静态内部类的实例。
class Outer{
//相当于外部类的一个静态成员
static class Inner{
}
}
public class TestStaticInnerClass {
public static void main(String[] args) {
//通过 new 外部类名.内部类名() 来创建内部类对象
Outer.Inner inner =new Outer.Inner();
}
}
匿名内部类
适合那种只需要使用一次的类。比如:键盘监听操作等等。
new 父类构造器(实参类表) \实现接口 () {
//匿名内部类类体!
}
this.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
this.addKeyListener(new KeyAdapter(){
@Override
public void keyPressed(KeyEvent e) {
myTank.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
myTank.keyReleased(e);
}
}
);
局部内部类
定义在方法内部的,作用域只限于本方法
public class Test2 {
public void show() {
//作用域仅限于该方法
class Inner {
public void fun() {
System.out.println("helloworld");
}
}
new Inner().fun();
}
public static void main(String[] args) {
new Test2().show();
}
}
5.11.3阅读API文档
5.11.4 String类常用的方法
String类常用方法实例
public class StringTest1 {
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 s = s1.replace(' ', '&');//将s1中的空格替换成&
System.out.println("result is :" + s);
}
}
public class StringTest2 {
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();//转小写
System.out.println(s);
s = s1.toUpperCase();//转大写
System.out.println(s);
String s2 = " How old are you!! ";
s = s2.trim();//去除字符串首尾的空格。注意:中间的空格不能去除
System.out.println(s);
System.out.println(s2);//因为String是不可变字符串,所以s2不变
}
}
xxx
课后部分习题
2.以下关于继承条件下构造方法执行过程的代码的执行结果是( )。(选择一项)
class Person {
public Person() {
System.out.println("execute Person()");
}
}
class Student extends Person {
public Student() {
System.out.println("execute Student() ");
}
}
class PostGraduate extends Student {
public PostGraduate() {
System.out.println("execute PostGraduate()");
}
}
public class TestInherit {
public static void main(String[] args) {
new PostGraduate();
}
}
A.execute Person()
execute Student()
execute PostGraduate()
B.execute PostGraduate()
C.execute PostGraduate()
execute Student()
execute Person()
D.没有结果输出
//所有子类会先用super()方法调用父类构造方法,再调用自己的构造方法
3.编译运行如下Java代码,输出结果是( )。(选择一项)
class Base {
public void method(){
System.out.print ("Base method");
}
}
class Child extends Base{
public void methodB(){
System.out.print ("Child methodB");
}
}
class Sample {
public static void main(String[] args) {
Base base= new Child();
base.methodB();
}
}
A.Base method
B.Child methodB
C.hild methodB
D.编译错误
//上转型对象无法使用对象的新增方法,只能使用继承或重写的方法
4.在Java中关于abstract关键字,以下说法正确的是( )。
A.abstract类中可以没有抽象方法
B.abstract类的子类也可以是抽象类
C.abstract方法可以有方法体
D.abstract类可以创建对象
A.abstract类可以有abstract方法,也可以有非abstrct方法
B:非abstract类为abstract类的子类的话,必须重写父类方法,如果子类也是abstract类的话,可以继承或重写abstra方法
D:abstract类不能new对象,但可以成为子类的上转型对象,此时该对象可以调用子类的重写方法
————————————————
版权声明:本文为CSDN博主「流雪扶风」的原创文章截取,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_34834846/article/details/81412804
5.在Java接口中,下列选项中属于有效的方法声明是( )。(选择二项)
A.public void aMethod( );
B.final void aMethod( );
C.void aMethod();
D.private void aMethod( );
B:final可以修饰接口变量,但不能修饰接口方法,因为接口的方法是是抽象方法,必须通过子类继承重写来实现
D:接口的方法一定是public的,以在其他类中实现