이 기사는 이전 기사에서 이어집니다. java - 객체 지향에 대한 자세한 소개(1)
11. 상위 클래스에 대한 하위 클래스 액세스 및 메서드 재정의
하위 클래스는 상위 클래스의 전용 멤버에 직접 액세스할 수 없습니다.
그러나 하위 클래스는 상위 클래스의 비공개 메서드를 호출하여 상위 클래스의 비공개 멤버에 간접적으로 액세스할 수 있습니다.
Person 클래스에는 개인 필드 이름이 있으며, Student는 Person을 상속받습니다.
new Sudent().name; 클래스의 특별한 경우)
주로 상위 클래스를 기반으로 하며 자체 필드와 메서드를 추가합니다.
메서드 재정의 이유:
부모 클래스의 메서드가 하위 클래스에 적합하지 않은 경우 하위 클래스는 상위 클래스와 동일한 메서드를 갖습니다.
가장 좋은 판단 방법: 앞에 @를 추가합니다. 하위 클래스 메서드 Override를 컴파일하고 전달할 수 있으며 이는 해당 메서드의 재정의임을 나타냅니다.
하위 클래스는 상위 클래스 메서드를 재정의해야 합니다.
부모 클래스의 메서드가 하위 클래스 자체의 특징적인 동작에 적합하지 않은 경우 부모 클래스에서 변경해야 하는 메서드를 재정의해야 합니다.
12. super 키워드와 상위 클래스 생성자 호출
은 상위 클래스 객체의 기본 참조를 나타냅니다.
super를 사용하여 상위 클래스의 생성자 메서드 호출
생성자 호출
이 클래스에서 오버로드된 다른 생성자를 호출하려면 이(매개변수 목록)를 사용하세요.
하위 클래스 생성자는 super(매개변수 목록)를 사용하여 상위 클래스 생성자를 호출합니다
하위 클래스가 상위 클래스의 생성자를 호출하는 경우: #🎜🎜 #
super는 첫 번째 문장에 배치되어야 합니다. Java는 하위 클래스의 생성자를 실행하기 전에 먼저 상위 클래스의 매개변수 없는 생성자를 호출합니다. 목적은 상위 클래스의 멤버가 초기화 작업을 수행하는 것입니다. .하위 클래스가 객체를 생성할 때 기본적으로 상위 클래스의 인수 없는 생성자를 호출합니다. 하위 클래스 생성자가 상위 클래스의 다른 생성자를 호출하도록 명시적으로 지정하면 지정된 상위 클래스는 다음을 수행합니다. 클래스 생성자가 호출되면 인수가 없는 부모 클래스 생성자에 대한 호출을 취소합니다.
Eg: package reviewDemo; class A{ String name; A(){ System.out.println("父类默认隐式的构造方法!"); } A(String name){ System.out.println("父类显式的构造方法!"); } } class B extends A{ B(){ super(null); System.out.println("子类默认隐式的构造方法!"); } } public class Demo10 { public static void main(String[] args) { new B(); } }
13. 객체 지향 다형성
#🎜 🎜 #다형성:동일한 개체가 동시에 여러 형태를 갖는 것을 말합니다
예를 들어 국수집에 국수를 먹으러 가서 국수를 먹고 싶다고 하면 사장님이 쇠고기 국수를 주실 수 있습니다. , egg Noodles 등
이것은 "얼굴"이 여러 형태를 가지고 있다는 것을 의미하며, 이는 엔터티가 여러 형태를 가지고 있음을 의미합니다.
컴파일 시 유형은 유형에 따라 결정됩니다. 변수를 선언할 때 사용되는 유형은 실제로 변수에 할당된 개체에 따라 결정됩니다.
컴파일 타임 유형과 런타임 유형이 다르면 다형성이 발생합니다.
예:
전제:학생 확장 Person:
Person p = new Person();<code>Student extends Person:
Person p = new Person()
;
Student s = new Student()
;
Person p = new Student()
학생 s = new Student()
;
Person p = new Student()
; //다형성참조 관계: 부모 클래스 변수는 하위 클래스 인스턴스 객체를 가리킵니다
다형성을 달성하는 메커니즘:
# 🎜 🎜#상위 클래스의 참조 변수는 하위 클래스의 인스턴스 객체를 가리킬 수 있으며, 프로그램이 호출하는 메소드는 런타임 중에 동적으로 바인딩되는데, 이는 참조 변수가 가리키는 실제 인스턴스 객체의 메소드이며, 참조 변수의 유형에 정의된 메서드 대신 메모리에서 실행되는 개체입니다.
다형성의 역할:
다른 하위 클래스 개체를 상위 클래스로 생각하세요. 상위 클래스는 서로 다른 하위 클래스의 개체를 보호할 수 있습니다. 공통 코드를 작성하고 변화하는 요구에 적응할 수 있는 공통 프로그래밍을 만듭니다.
메서드 선언이 아닌 메소드 구현만 수정
다형성의 전제조건은 상속입니다;
# 🎜 🎜#카테고리:컴파일 시간 다형성: 메서드 오버로딩런타임 다형성: 메서드 재정의Eg: package test; class Dog{ void eat(){ System.out.println("一般的狗吃一般的狗粮!"); } } class HashDog extends Dog{ void eat(){ System.out.println("哈士奇吃哈士奇的狗粮!"); } } class ZangAoDog extends Dog{ void eat(){ System.out.println("藏獒吃藏獒的狗粮!"); } } //定义一个动物园喂的方法 class Zoo{ void feed(Dog d){ d.eat(); } } public class Demo11 { public static void main(String[] args) { Dog hd = new HashDog(); Dog zd = new ZangAoDog(); Zoo z = new Zoo(); z.feed(hd); z.feed(zd); } }출력: #🎜🎜 #
허스키는 허스키 강아지 사료를 먹습니다!
티베탄 마스티프는 티베탄 마스티프 개사료를 먹습니다!
14. 참조변수형 변환
상위변환(하위클래스 → 상위클래스): (자동완성)
#🎜 🎜 # 상위 클래스 객체 = 하위 클래스 인스턴스; 하향 변환(상위 클래스→하위 클래스): (강제 완료) 하위 클래스 이름 하위 클래스 객체 = (하위 클래스 이름) 상위 클래스 인스턴스; 객체 이름 인스턴스of 클래스 이때 지정된 변수 이름이 참조하는 실제 유형이 현재 지정된 클래스인지 하위 클래스인지 확인합니다.#🎜🎜 #나의 요약: 객체의 유형과 클래스는 상속 관계를 가져야 합니다
Eg: class A extends B{} B b = new A(); If(b instanceof A){ ... }
2、面向对象(2)
1、基本数据类型的包装类
引言:Java提倡的万物皆对象,但是数据类型的划分出现了基本数据类型和引用数据类型,那么我们怎么能把基本数据类型称为对象呢?
除了Integer和Character定义的名称和对应的基本类型差异大,其他六种都是将首字母大写就可以了。
Integer,Byte,Float,Double,Short,Long都是Number类的子类。(Number类后面讲);
Character和Boolean都是Object直接子类;
8个类都是final修饰的(不可被继承)。
2、基本数据类型和包装类相互转换
把基本数据类型 → 包装类:
通过对应包装类的构造方法实现
除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。
包装类 → 基本数据类型
包装类的实例方法xxxValue(); // xxx表示包装类对应的基本数据类型
Eg: boolean bool = false; Boolean b2 = new Boolean(bool); Integer i = new Integer(3); int i2 = i.intValue(); Boolean b1 = new Boolean("TRue");//true boolean b2 = b1.booleanValue(); Float f = new Float("3.14");//3.14 Integer i2 = new Integer("123s");//NumberFormatException
备注:
自动装箱&自动拆箱
jdk1.5开始出现的特性:
自动装箱:可把一个基本类型变量直接赋给对应的包装类对象或则Object对象
自动拆箱:允许把 包装类对象直接赋给对应的基本数据类型
Eg: Integer i = 3;//装箱 int i2 = i;//拆箱 Object flag = new Boolean(false); if(flag instanceof Boolean){ Boolean b = (Boolean)flag; boolean b2 = b; }
3、基本类型和String之间的转换
String → 基本类型,除了Character外所有的包装类提供parseXxx(String s)静态方法,用于把一个特定的字符串转换成基本类型变量;
基本类型 → String,String 类有静态方法valueOf(),用于将基本类型的变量转换成String类型。
String str = "17"; int i = Integer.parseInt(str);//String --> 基本类型 String s1 = String.valueOf(i);//基本类型 --> String
4、Object类
所有类的公共父类,一旦一个类没有显示地继承一个类则其直接父类一定是Object。
一切数据类型都可用Object接收
class OOXX extends Object{}等价于class ooXX {}
常见方法
public boolean equals(Object obj)
:对象比较
public int hashCode()
:取得该对象的Hash码
public String toString()
:对象描述
Object类的 toString()方法:“对象的描述”
建议所有类都覆写此方法
直接打印输出对象时,会调用该对象的toString()方法。//可以不写出来
打印对象的时候,实际调用的对象实际指向的类的自我描述;
全限定类名+@+十六进制的hashCode值,等价于
全限定类名+@+IntegertoHexString(该对象.hashCode)
equals也是判断是否指向同一个对象
没有实际意义,有必要可以重写
public boolean equals(Object obj) {}
String 覆写了 Object的equals方法:只比较字符的序列是否相同
==用于判断两个变量是否相等
基本类型:
引用类型:必须指向同一个对象,才true
只能比较有父子或平级关系的两个对象
new String("1") == new String("1"); ?
5、代码块
代码块指的是使用"{}"括起来的一段代码,根据代码块存在的位置可以分为4种:
普通代码块;
构造代码块;
静态代码块;
同步代码块(线程同步的时候讲解)。
代码块里变量的作用域:
只在自己所在区域(前后的{})内有效;
普通代码块:
普通代码块就是直接定义在方法或语句中定义的代码块:
public void show(){
普通代码块
}
构造代码块:
直接写在类中的代码块:
优先于构造方法执行,每次实例化对象之前都会执行构造代码块。
Eg: public class Demo { { System.out.println("我是构造代码块"); } public Demo(){ System.out.println("我是构造方法"); } public static void main(String[] args) { Demo d1 = new Demo(); Demo d2 = new Demo(); } }
静态代码块
使用static 修饰的构造代码块:
优先于主方法执行,优先于构造代码块执行,不管有创建多少对象,静态代码块只执行一次,可用于给静态变量赋值;
Eg: package reviewDemo; /** * 测试各代码块的优先级 * 优先级顺序:静态代码块 > 构造代码块 > 普通代码块 * 备注:无论创建几个对象,静态代码块只执行一次! */ public class Demo13 { Demo13(){ System.out.println("我是构造方法!"); } { System.out.println("我是构造代码块!");//实例化对象的时候才会去调用! } static{ System.out.println("我是静态代码块!"); } public static void main(String[] args) { new Demo13(); new Demo13();//再次创建对象,证明无论创建几次对象,静态代码块都只执行一次 System.out.println("我是普通代码块!"); } }
输出:
我是静态代码块!
我是构造代码块!
我是构造方法!
我是构造代码块!
我是构造方法!
我是普通代码块!
6、构造方法的私有化
有的时候我们为了避免外界创建某类的实例,就将某类的构造方法私有化,即将它的构造方法用private修饰:
外界如何用到?
提供get方法!不提供的话外界就没法创建对象!(对反射无效)
Eg:package reviewDemo; class Stu{ //将构造方法私有化 private Stu(){ } } public class Demo15 { public static void main(String[] args) { Stu s = new Stu(); } }
Singleton模式(单例模式) 饿汉式和懒汉式
目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例。
好比一个国家就只有一个皇帝(XXX),此时每个人叫的“皇帝”都是指叫的XXX本人;
常见单例模式类型:
饿汉式单例:直接将对象定义出来
懒汉式单例:只给出变量,并不将其初始化;
我的总结:
饿汉式,static修饰,随着类的加载而加载,会损耗性能,但是方法相对简单
懒汉式 第一次用的时候相对较慢,因为需要加载!线程,不安全!
package reviewDemo; //单例模式 //饿汉式,直接把对象构造出来 class SingleDemo{ private static SingleDemo s1 = new SingleDemo(); private SingleDemo(){ //提供私有化的构造方法,那么外界就不能构造对象了! } public static SingleDemo getS1() { return s1; } } //懒汉式,先定义,但是不创建对象 class SingleDemo2{ private static SingleDemo2 s3 ; private SingleDemo2(){ //提供私有化的构造方法,那么外界就不能构造对象了! } public static SingleDemo2 getS3() {//这是一个方法,返回值为创建的对象! if(s3 == null){ s3 = new SingleDemo2(); }//和饿汉式的区别,此时才来创建对象! return s3; } } public class Demo14 { public static void main(String[] args) { SingleDemo s1 = SingleDemo.getS1(); SingleDemo s2 = SingleDemo.getS1(); SingleDemo2 s3 = SingleDemo2.getS3(); SingleDemo2 s4 = SingleDemo2.getS3(); System.out.println(s1 == s2); System.out.println(s3 == s4); } } 输出:true true 备注:枚举更加安全些 package reviewDemo; enum Stu{ jake; //将构造方法私有化起来,反射也不能创建对象,安全 private Stu(){ } } public class Demo15 { public static void main(String[] args) { } }
8、final 关键字
final可以修饰类,方法,变量。
final修饰类不可以被继承,但是可以继承其他类。
final修饰的方法不可以被覆写,但可以覆写父类方法。
final修饰的变量称为常量,这些变量只能赋值一次。
内部类在局部时,只可以访问被final修饰的局部变量。
final修饰的引用类型变量,表示该变量的引用不能变,而不是该变量的值不能变;
Eg: package reviewDemo; final class Name{ } class NewName extends Name{//ERROR,报错,因为Name有final修饰 } public class Demo15 { public static void main(String[] args) { } }
9、抽象类
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。
但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。
抽象方法的定义:通过abstract关键字来修饰的类称为抽象类;
总结:抽象类用private修饰,里面可以有用private修饰的方法(没有方法体),强制子类进行覆写;
可以理解为:具有某些公共方法的一个总结类。
可以定义被abstract修饰的抽象方法
抽象方法只有返回类型和方法签名,没有方法体。
备注:
抽象类可以含有普通方法
抽象类不能创建实例对象(不能new)
需要子类覆盖掉所有的抽象方法后才可以创建子类对象,否则子类也必须作为抽象类
列举常见的几个抽象类:
流的四个基本父类
InputStream,OutputStream,Reader,Writer
我的总结:
抽象类是类的一种特殊情况:据有类的一切特点,但是不能实例化;一般的都得带有抽象方法。
抽象类不可以实例化,有时看到的近似实例化是多态机制的体现,并不是真正的实例化。
Eg: Socket s = new Socket(); OutputStream os = s.getOutputStream(); 左边是OutputStream类型变量的声明,右边是获取抽象类OutputStream的一个实例对象! package testDemo2; abstract class Person{ } class Student extends Person{ } public class Demo2 { public static void main(String[] args) { Person p = new Student();//体现的是多态,父类声明实例化子类对象。而不是抽象类实例化 } }
abstract方法
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是功能声明相同,但功能主体不同。
那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
abstract [非private访问修饰符] 返回值类型 方法名称(参数列表);
抽象方法要存放在抽象类中。
抽象方法也可以存在于接口中
Eg: package reviewDemo; abstract class Person3{ abstract void show(); abstract void inof(); void turn(){ } } class NewP extends Person3{ @Override void show() { } @Override void inof() { } //不覆写的话会报错 } public class Demo15 { public static void main(String[] args) { //new Person3();报错!因为抽象类不可以实例化 } }
10、抽象类的体现-模板模式
抽象类是多个具体子类抽象出来的父类,具有高层次的抽象性;以该抽象类作为子类的模板可以避免子类设计的随意性;
抽象类的体现主要就是模板模式设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行拓展,但是子类在总体上大致保留抽象类的行为方式;
编写一个抽象父类,该父类提供了多个子类的通用方法,并把一个或多个抽象方法留给子类去实现,这就是模板设计模式;
模板模式应用的简单规则:
1.抽象父类可以只定义需要使用的某些方法,其余留给子类去实现;
2.父类提供的方法只是定义了一个通用算法,其实现必须依赖子类的辅助;
我的总结:
如果父类的方法不想被子类覆写,那么可以在前面加上final关键字修饰。
Eg: package reviewDemo; //模板模式 //抽象类中包含很多的抽象方法,子类必须去覆写! abstract class Method{ abstract double mul();//返回值类型如果是void的话,下面报错,因为没有返回值,无法引用! abstract double divid(); void show(){ System.out.println("面积是:"+mul());//周长 System.out.println("面积是:"+divid());//面积 } } class Square extends Method{ double d; public Square(double d) { super(); this.d = d; } @Override double mul() { return d * d; } @Override double divid() { return 4 * d; } } class Cirle extends Method{ double r; public Cirle(double r) { super(); this.r = r; } @Override double mul() { return 2 * 3.14 * r; } @Override double divid() { return 3.14 * r * r; } } public class Demo16 { public static void main(String[] args) { Square s = new Square(5); s.show(); Cirle c = new Cirle(4); c.show(); } }
以上是本次整理的关于java面向对象的详细讲解,后续会为大家继续整理。
文中若有明显错误请指正,谢谢!
더 많은 JAVA 관련 질문을 보려면 PHP 중국어 웹사이트를 방문하세요. JAVA 비디오 튜토리얼
위 내용은 Java——객체 지향에 대한 자세한 소개(2)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!