1.this的使用
- 在方法中可以通过this关键字表示调用该方法的对象。
- 通常在类中使用this区分成员变量和参数,如果没有歧义,可以省略this。
- 一个类可以创建多个对象(存储于堆中),但方法只有一份(存储于方法区中)。
- 代码
package day2;
class Phone{
int memery; // 内存 64,128,256
String pinpai; // 品牌
// 成员方法
public void updataMemery(int memry){
//this : 代词,指代当前对象(谁调用方法,谁就是this)
this.memery = memery;
}
}
public class ThisDemo {
public static void main(String[] args) {
Phone p1 = new Phone();
p1.memery = 64;
p1.pinpai = "华为p40";
Phone p2 = new Phone();
p2.memery = 64;
p2.pinpai = "小米xs";
p1.updataMemery(128);
p2.updataMemery(256);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JA1emaRo-1691867316502)(https://gitee.com/ok_ok_ok/pic/raw/master/img/202307272021262.png)]
2.继承
类型定义的时候,可以抽取出其中的公共属性和公共方法定义在父类中,然后定义子类。子类继承这个
父类定义的属性和方法,子类中只需要写自己独有的属性和方法。
2.1extends 关键字
- extends关键字可以实现类的继承
- 子类(sub class) 可以继承父类(super class)的成员变量及成员方法。同时也可以定义自己的成员变量和成员方法。
- java语言不支持多继承,一个类只能继承一个父类。 但一个父类可以有多个子类。
package day2;
public class Shape {
int x; // 坐标轴上的x
int y; // 坐标轴上的y
// 输出坐标位置
void print(){
System.out.println("(" + x + "," + y + ")");
}
}
class Rect extends Shape{ // 坐标轴上的某个x,y位置,有个宽,高为多杀的矩形
double width;
double height;
// 计算面积,, 计算周长
public double girth(){
return 2*(width + height);
}
public double area() {
return width * height;
}
}
class Circle extends Shape{// 坐标轴上的某个x,y位置,有个半径是多少的圆
double r; // 圆的半径
// 计算面积, 计算周长
public double area(){
return Math.PI * r * r;
}
public double girth() {
return 2 * Math.PI * r;
}
}
class DengBianTriangle extends Shape{ // 坐标轴上的某个x,y位置,有个三角形
double width;
public double area() {
return 1.0/2.0 * width*width;
}
public double girth(){
return 3 * width;
}
}
2.2 向上造型
-
一个子类的对象可以向上造型为父类的类型
Father f = new Sun();
- java编译器编译的时候根据父类型检查调用的成员变量和成员方法是否匹配。
package day2;
//向上造型的使用: 子类对象的引用该地址,赋值给一个父类的引用
public class TestShape {
public static void main(String[] args) {
Rect rect = new Rect();
// 向上造型
Shape shape = new Rect(); // 向上造型
//设置一个宽度是4,高度是5的矩形,计算矩形的周长和面积
//shape.width = 4; // 编译错误: 编译的时候,以=号左边的类型为准,这个时候是父类Shape,没有width属性
//向上造型后之后,只能通过引用访问到引用对应的类型属性和方法
shape.print();
shape.x = 0;
shape.y = 0;
//数据类型强制转换:被强转的引用,是能转化为某种类型的,,才可以使用强转的语法规则,否则抛出异常
Rect r1 = (Rect)shape; // 把数据类型转换之后,就可以操作属性和方法了
r1.width = 4;
r1.height = 5;
System.out.println("周长:" + r1.girth());
System.out.println("面积:" + r1.area());
}
}
-
引用和类的类型的使用
-
类名.class ,可以获取类型名
-
引用.getClass()方法 ,可以获取引用指向的对象的类名。
-
//向上造型
Shape s1 = new Circle();
Shape s2 = new DengBianTriangle();
// ** 把s1 强转为矩形
//Rect r2 = (Rect)s1; // ClassCastException: 类型转换异常
// *** getClass() 方法,可以获取引用指向对象的类名
System.out.println(s1.getClass());
System.out.println(Rect.class);
// *** 类名.class, 可以获取类型名
// *** 先判断类型是否相同,相同则强转。
if(s1.getClass() == Rect.class){
Rect r2 = (Rect)s1;
}else{
System.out.println("类型不同,不能强转");
}
if(s1.getClass() == Circle.class){
Circle c1 = (Circle)s1;
System.out.println("强转成功");
}else{
System.out.println("类型不同,不能强转");
}
2.3instanceof关键字
- 对于一个父类的引用类型,可以指向该类的对象也可以指向其任意一个子类型的对象。
- 通过instanceof 关键字判断引用指向的对象的实际类型。
- 根据引用指向的实际类型,将引用强制转换为实际类型。
package day2;
//instanceof关键字 : 运算结果是boolan类型,用于判断某个指向的引用对象, 是否是某种类型
public class TestRect {
public static void main(String[] args) {
Shape s = new Rect();
Rect r = new Rect();
if (s instanceof Rect){
System.out.println("s指向的对象是Rect类型");
}
if (r instanceof Rect){
System.out.println("r指向的对象是Rect类型");
}
// ** 通过类的类型比较进行判断
if (r.getClass() == Rect.class) {
System.out.println("r指向的对象是Rect类型");
}
}
}
2.4super关键字 & super函数
- 子类中可以使用super关键字,调用父类的属性和方法
- 子类的构造方法中必须通过super调用父类的构造方法。因为创建子类之前,必须先创建父类。
- 子类的构造函数如果没有直接使用super调用父类构造方法,java编译器会自动的加入对父类无参构造函数的调用(那么要求父类必须有无参构造方法)。
package day2;
//super:调用父类 的方法,属性
public class SuperDemo {
public static void main(String[] args) {
Son son = new Son();
//System.out.println(son.m + " " + son.n);
son.sayHi();
son.print();
}
}
class Father {
int x ;
int y;
public void sayHi(){
System.out.println("hello");
}
public Father(){
System.out.println("Father -- 无参");
}
public Father(int x , int y){
this.x = x;
this.y = y;
System.out.println("Father --- 两个参数的");
}
}
class Teather extends Father{
int m ;
int a;
}
class Son extends Father{
int m ;
int n;
public Son(){
//super(); // ---super()函数,表示调用父类无参构造函数
super(3,6); // ---super(int, int)函数,
}
public Son(int m, int n){ // 给自己的(包含继承来的)成员变量初始化
super(3,3);
this.m = m;
this.n = n;
}
public Son(int m){
//super(3); // 编译错误, 父类不存在一个int类型参数的构造函数
this.m = m;
}
public Son(int m , int n, int x){
this.m = m;
this.n = n;
this.x = x;
}
public void print(){
int k = super.x;
int k1 = super.y;
int k2 = x + y; // super可以省略,继承了父亲的属性,可以直接使用
super.sayHi();
//sayHi(); // 省略了super。继承了父类的方法,可以直接使用
}
public void sayHi() {
super.sayHi(); // 调父类方法
//没有用super来指定调用父类方法。优先调用自己的方法,如果自己没有,再调用父类方法
//sayHi(); // StackOverflowError
}
}
2.5重写(override)
- 子类从父类继承的方法,如果不能满足子类的需要,可以重写父类的方法。即方法名和参数列表和父类保持完全一致,方法的实现不同。
- 子类重写父类的方法之后,子类对象优先调用自己的方法。
- 子类重写父类的方法的时候,可以在重写的方法中,使用super关键字调用到父类的方法。
- 子类重写了父类的方法,要么就调用子类自己的方法,否则就调用父类的方法。
package day2;
public class Art {
public void paint(){
System.out.println("艺术家");
}
}
class HuaJia extends Art{
@Override // -- 注解( @ + 类型名) ,对类, 对方法, 对属性进行特殊功能的设置
// @Override -- 重写, 放在方法前, 表示该方法必须重写父类方法
public void paint() {
//super.paint(); // -- 调用父类的方法。根据情况,是否要删除该行代码。
System.out.println("这是画家,用颜料画画。");
}
}
class ShuFaJia extends Art{
@Override
public void paint() {
System.out.println("这是书法家,用笔书写。");
}
}
class DiaoSuJia extends Art{
@Override
public void paint() {
System.out.println("这是雕塑家,用刀雕刻。");
}
}
class GangQinJia extends Art{
}
// ** 子类重写了父类的方法,那么就调用子类自己的方法,否则就调用父类的方法
class TestArt{
public static void main(String[] args) {
Art art = new DiaoSuJia();
art.paint(); // 调用子类自己的paint方法
Art art1 = new HuaJia();
art1.paint(); // 调用子类自己的paint方法
Art art2 = new ShuFaJia();
art2.paint(); // 调用子类自己的paint方法
Art art3 = new GangQinJia();
art3.paint(); // 调用父类的paint方法 , 如果自己没有,就调用父类的方法
}
}
3.package关键字
- 定义类的时候需要指定类的名称。但是如果仅仅将类名作为类的唯一标志,则会出现命名冲突的问
- 题。
- 在java中,使用package 来解决命名冲突的问题。因此定义类的时候,一般需要先给类指定一个包名。
- 类的真实名字是: 包名 + 类名。
- 包名可以有层次结构,一个类可以有多层包名。
- 建议包名和类名不要和jdk中的重名。
- 如果各个公司和组织的程序员都随意命名包,并不能很好的解决命名冲突问题。因此指定包名的时候建议使用: 公司域名反写 + 项目名 + 项目模块名 + mvc模式分层
4.import关键字
-
如果要在程序中,使用某个类,可以用该类的全名,这样比较复杂。
java.util.Date date = new java.util.Date();
-
一般使用import 语句导入这个类,然后使用该类。
i
mport com.hqyj.crmservice.util.Shape;
import java.util.*; // *表示java.util包中的所有类,一般建议使用谁,导入谁,不要全部
导入。
5.访问控制符
5.1访问控制符public 和 private
-
private修饰的成员变量和方法仅仅只能在本类中调用,因此private修饰的内容是对内实现数据的
封装,如果“公开”会增加维护的成本。
-
public修饰的成员变量和方法可以在任何地方调用,因此public修饰的内容是对外可以被调用的功
能。
-
在定义类的时候,一般采用成员变量私有化,方法公开的原则。
5.2访问控制符protected 和默认访问控制
- 用protected修饰的成员变量和方法可以被子类及同一个包中的类使用。
- 默认访问控制即不书写任何访问控制符,默认访问控制的成员变量和方法可以被同一个包中的类调
用。
5.3访问控制符权限对比
同一个类中
package day2;
// 访问权限的设置
public class Demo1 {
private String name;
String sex;
protected String hobby; //
public String keyword; // 关键*/-
//同一个类中,都能访问
void print(){
System.out.println(name);
System.out.println(sex);
System.out.println(hobby);
System.out.println(keyword);
}
}
同包中
class TestA{
public static void main(String[] args) {
Demo1 d = new Demo1();
//d.name = ""; // 私有变量,只能在自己的类被访问到
d.sex = "男"; // 同包中可以访问 ; 默认修饰。 protected ,public
d.hobby = "看书";
d.keyword = "自信";
}
}
不同包中,有继承
public class SubDemo2 extends Demo1 {
void print(){
// System.out.println(name); // 私有变量,只能再自己的类中被访问到。
// System.out.println(sex); // 不同包中访问不了。
System.out.println(hobby); // 不同包中,有继承关系
System.out.println(keyWord); // 不同包中,有继承关系
}
}
不同包中,不同类中,没有继承
public static void main(String[] args) {
Demo1 demo1 = new Demo1();
// System.out.println(demo1.name); // 不同包的其他类,不能使用。
//System.out.println(demo1.sex); // 不同包的其他类,不能使用。
//System.out.println(demo1.hobby); // 不同包的其他类,不能使用。
System.out.println(demo1.keyWord); // 不同包的其他类中。
}