-
学习包 package,给你的类指定包名
-
学习面向对象的三大特性:封装、继承、多态
-
学习抽象类 abstract class、内部类 inner class
-
学习接口interface,了解接口的特性,接口默认方法等
-
了解什么是代码块、了解如何进行类属性初始化
-
学习方法,构造方法、静态方法、实例方法、方法重载、方法重写,方法传参
-
学习this关键字,通过this访问属性、访问构造方法;学习 super关键字,通过super调用父类的属性和方法
-
学习什么是枚举类型,枚举一个类型枚举 CategoryEnum.java 设置属性:FRUIT、CLOTHES、PHONE、BOOKS
-
(选做)写3种单例模式
1、包 package,给类指定包名
Java的包名都有小写单词组成,类名首字母大写;
为了保障每个Java Package命名的唯一性,要求开发人员在自己定义的包名前加上唯一的前缀。由于互联网上的域名称是不会重复的,所以多数开发人员采用自己公司在互联网上的域名称作为自己程序包的唯一前缀。例如: com.sun.swt.……;
一种命名方法
indi :
个体项目,指个人发起,但非自己独自完成的项目,可公开或私有项目,copyright主要属于发起者。
包名为“indi.发起者名.项目名.模块名.……”。
pers :
个人项目,指个人发起,独自完成,可分享的项目,copyright主要属于个人。
包名为“pers.个人名.项目名.模块名.……”。
priv :
私有项目,指个人发起,独自完成,非公开的私人使用的项目,copyright属于个人。
包名为“priv.个人名.项目名.模块名.……”。
onem :
与“indi”相同,推荐使用“indi”。
team :
团队项目,指由团队发起,并由该团队开发的项目,copyright属于该团队所有。
包名为“team.团队名.项目名.模块名.……”。
com :
公司项目,copyright由项目发起的公司所有。
包名为“com.公司名.项目名.模块名.……”。
https://www.cnblogs.com/cht-/p/11968668.htmlhttps://www.cnblogs.com/cht-/p/11968668.html
2、封装、继承、多态
2.1 封装
封装:是面向对象方法的重要原则,就是把对象的属性和行为(数据)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节,就是把不想告诉或者不该告诉别人的东西隐藏起来,把可以告诉别人的公开,别人只能用我提供的功能实现需求,而不知道是如何实现的。通过封装增能够加安全性。
示例
public class Person {
private String name;
private int gender;
private int age;
public String getName() {
return name;
}
public String getGender() {
return gender == 0 ? "man" : "woman";
}
public void work() {
if (18 <= age && age <= 50) {
System.out.println(name + " is working very hard!");
} else {
System.out.println(name + " can't work any more!");
}
}
}
以上 Person 类封装 name、gender、age 等属性,外界只能通过 get() 方法获取一个 Person 对象的 name 属性和 gender 属性,而无法获取 age 属性,但是 age 属性可以供 work() 方法使用。
注意到 gender 属性使用 int 数据类型进行存储,封装使得用户注意不到这种实现细节。并且在需要修改 gender 属性使用的数据类型时,也可以在不影响客户端代码的情况下进行。
2.2 继承
继承:是面向对象最显著的一个特性,继承是从已有的类中派生出新的类称为子类,子类继承父类的数据属性和行为,并能根据自己的需求扩展出新的行为。通过继承能够 提高了代码的复用性。
如果在父类中拥有私有属性(private修饰),则子类是不能被继承的。
Animal animal = new Cat();
继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。
里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
- 子类中可以增加自己特有的方法
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松
- 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等
Java之封装,继承,多态 - 奋进的小样 - 博客园 (cnblogs.com)https://www.cnblogs.com/fenjyang/p/11462278.html
2.3 多态
多态:指允许不同的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。封装和继承几乎都是为多态而准备的,在执行期间判断引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态分为编译时多态和运行时多态。编译时多态主要指方法的重载,运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。
注意:在多态中,编译看左边,运行看右边
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}
3、抽象类 abstract class、内部类 inner class
3.1 抽象类
抽象类:抽象类是只声明方法的存在而不去具体实现它的类。抽象类不能被实例化,也就是不能创建其对象。使用abstract关键字定义抽象类,直接上例子。
下面是一个抽象类的定义,在class前直接加上abstract关键字。最后一句“public abstract void voice();”是一个抽象方法,没有实际意义,必须用子类重写。需要注意的是,抽象方法只有方法的声明,而没有方法的实现,与接口类似,但是用abstract关键字修饰的。对于抽象方法前的修饰,不能使用private或static关键字。
//抽象类
abstract class Animal { // 定义抽象类
public String animal; // 定义颜色成员变量
public Animal() { // 定义构造方法
animal="bird";
}
public abstract void voice(); // 定义抽象方法
}
//抽象方法
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("woof...");
}
}
public class Cat extends Animal {
@Override
public void voice() {
System.out.println("nya...");
}
}
https://www.cnblogs.com/adamjwh/p/8366196.htmlhttps://www.cnblogs.com/adamjwh/p/8366196.html
3.2 内部类
内部类:在一个类中再定义一个类,就将在类中再定义的那个类称为内部类。分为成员内部类、静态内部类、局部内部类以及匿名内部类。
3.2.1 成员内部类
该内部类嵌套在外部类内,我们需要先实例化外部类,然后再通过外部类实例化的对象来实例化内部类。内部类是可以访问到外部类的私有成员的。
public class Demo {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.get();//out:外部类
}
}
public class Outer {
private String str = "外部类";
public class Inner{
public void get(){
System.out.println(str);
}
}
}
3.2.2 静态内部类
静态内部类可以使用 static 关键字定义,静态内部类就不需要先实例化外部类再实例化内部类了,可以直接实例化内部类。如果外部类是非静态的,而内部类是静态的,那么内部类就无法在外部类实例化之前调用外部类的成员了。
public class Demo {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
System.out.println(inner.str2);//out:内部类
}
}
public class Outer {
String str = "外部类";
public static class Inner{
String str2 = "内部类";
}
}
3.2.3 局部内部类
局部内部类与局部变量一样,不能使用访问控制修饰符和static修饰符,局部内部类仅在当前方法中有效。
public class Outer {
public void test(){
class Inner{}//内部类
}
}
3.2.4 匿名内部类
顾名思义就是没有名称的类,可使用默认构造方法来生成匿名内部类的对象。在匿名内部类后需要加分号标识。接口是不能实例化的,而这个例子却可以。
public class Demo {
public static void main(String[] args) {
new test(){//实际上这里的效果跟test test = new test()相同
@Override
public void say() {
System.out.println("hello world!");
}
};
}
}
interface test{
void say();
}
4、接口interface,接口的特性,接口默认方法
接口与抽象类比较相似,但它并不是一个类,因此他并不是用class来声明,而是使用interface。抽象类和接口的区别在于,抽象类可以有具体实现和抽象方法,而接口只存在抽象方法。接口实现了约束和实现的分离。
- 接口的特性接口中的方法都是public abstract的,而且只能是public abstract的;
- 接口中可以含有变量,但是变量都是public static final的,而且只能是public的;
- 接口中的方法是不能在接口中实现的,只能由实现接口的来实现接口的方法。
类用implements关键词来实现接口。跟抽象类一样,实现了接口的类,就需要重写接口中的方法。与只能继承一个抽象类不同,类可以实现多个接口。 接口和接口直接也是可以互相继承的,同样也是使用extend来继承。虽然他有继承关系,但是接口里是不存在构造器的。
public class PersonImpl implements Person,Clothes{
@Override
public void run() {}
@Override
public void color() {}
@Override
public void say() {}
}
public interface Animal {
void run();
}
public interface Person extends Animal{
void say();
}
public interface Clothes {
void color();
}
https://www.icewindy.cn/2022/03/23/Java%E7%AC%94%E8%AE%B0%EF%BC%88%E4%BA%94%EF%BC%89%EF%BC%9A%E6%8A%BD%E8%B1%A1%E7%B1%BB%E3%80%81%E6%8E%A5%E5%8F%A3%E3%80%81%E5%86%85%E9%83%A8%E7%B1%BB/https://www.icewindy.cn/2022/03/23/Java%E7%AC%94%E8%AE%B0%EF%BC%88%E4%BA%94%EF%BC%89%EF%BC%9A%E6%8A%BD%E8%B1%A1%E7%B1%BB%E3%80%81%E6%8E%A5%E5%8F%A3%E3%80%81%E5%86%85%E9%83%A8%E7%B1%BB/
5、代码块、类属性初始化
5.1 代码块
5.1.1 普通代码块
写在方法里面的代码块就是普通代码块 ;
5.1.2 构造块
如果将一个代码块放在类里面,那么就是一个构造块。构造块的作用是为了给对象进行初始化;每次创建对象时,都会调用一次构造块,并且构造块的优先于构造函数执行。有对象的创建,才会调用构造块;
构造块与构造函数的区别在于:每个对象被构造块初始化的那部分变量拥有的初始值是一样的,构造块对所有对象的效果是一样的。然而每个对象可能会使用不同构造函数,不同的构造函数初始化对象的方式是不同的。
5.1.3 静态块
使用static修饰的代码块就叫做静态代码块或者直接叫静态块。
- 静态块在类加载时执行,且只会执行一次,执行顺序优先主函数、构造函数和构造块。
- 静态代码块主要用于初始化类中的static属性(类属性),而构造块是初始化对象中的属性。
- 一个类中可以有多个静态代码块, 执行顺序依照静态代码块的声明顺序。静态代码块可以在类的任意位置定义,在方法中不可以声明静态块。
5.2 类
5.2.1 无继承关系的类
静态代码块、构造代码块、构造函数和主函数的执行顺序为:
静态代码块>主函数>构造代码块>构造函数
在加上静态属性、普通属性,他们的初始化执行顺序就为:
静态变量、静态代码块 > 主函数 > 指定初始值的属性 > 构造代码块 > 构造函数
5.2.2 有继承关系的类
有继承关系的类,初始化顺序按如下进行:
- 执行父类的静态代码块,并初始化父类静态成员变量
- 执行子类的静态代码块,并初始化子类静态成员变量
- 执行父类的构造代码块,执行父类的构造函数,若普通成员变量指定了初始值则先执行初始值的赋值,然后返回执行构造函数
- 执行子类的构造代码块,执行子类的构造函数,若普通成员变量指定了初始值则先执行初始值的赋值,然后返回执行构造函数
https://www.cnblogs.com/myworld7/p/10053367.htmlhttps://www.cnblogs.com/myworld7/p/10053367.html
6、方法,构造方法、静态方法、实例方法、方法重载、方法重写,方法传参
6.1 构造方法
构造方法负责对象的初始化工作,为实例变量赋予合适的初始值。必须满足以下的语法规则:
- 方法名与类名相同;
- 不要返回类型(例如return、void等);
- 不能被static、final、native、abstract和synchronized修饰,不能被子类继承。
6.2 静态方法、实例方法
静态方法是在类中使用staitc修饰的方法,在类定义的时候已经被装载和分配。而非静态方法是不加static关键字的方法,在类定义时没有占用内存,非静态方法只有在类被实例化成对象时,对象调用该方法才被分配内存;
允许不创建对象而调用静态方法,是Java为了减少程序员调用某些常用方法时的麻烦,而允许程序员按照传统的C语言中使用函数的方式来使用方法。典型的例子是前面某些程序中使用"Math.ramdon()"来获取随机数。
静态方法只能访问静态成员,实例方法可以访问静态和实例成员。之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this。
main()方法是一个典型的静态方法,它同样遵循一般静态方法的规则,所以它可以由系统在创建对象之前就调用。
静态方法可以方便在没有创建对象的情况下来进行调用(方法/变量)
https://blog.csdn.net/qq_43378945/article/details/90054340https://blog.csdn.net/qq_43378945/article/details/90054340
6.3 方法重载
与C基本一致
6.4 方法重写
-
两同:
-
方法名相同
-
参数列表相同
-
-
两小:
-
子类返回值类型 <= 父类的返回值类型(注意此处说的是继承关系,不是值大小)
-
子类抛出异常 <= 等于父类方法抛出异常
-
-
一大
-
子类方法的修饰符权限要 >= 父类被重写方法的修饰符权限
-
修饰符的权限大小:public>protected>default>private;
-
被final、static、private修饰的方法不可重写
public class Demo {
public static void main(String[] args) {
newPhone newPhone = new newPhone();
newPhone.call();
}
}
class phone{
public void call(){
System.out.println("可以打电话");
}
}
class newPhone extends phone{
@Override
public void call() {
System.out.println("可以打视频了");
super.call();
}
}
https://www.cnblogs.com/csc0712/p/15260399.htmlhttps://www.cnblogs.com/csc0712/p/15260399.html
6.5 方法传参
1.形参是基本数据类型(在栈里面开内存):值传递;不会影响到实际参数。
(byte、short、char、int、long、float、double、boolean)
2.实参是引用数据类型(在堆里面开内存 new):地址值传递;会影响到实际参数。
特殊类型:String,包装类(Byte、Short、Character、Integer、long、Float、Double、Boolean)
(15条消息) 方法-重写-重载-传参_El girasol~的博客-CSDN博客https://blog.csdn.net/consoleMY/article/details/112690061
7、this关键字,通过this访问属性、访问构造方法;super关键字,通过super调用父类的属性和方法
7.1 this
this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。this 的用法在 Java 中大体可以分为3种:
1.普通的直接引用,this 相当于是指向当前对象本身。
2.形参与成员名字重名,用 this 来区分
class Person {
private int age = 10;
public Person(){
System.out.println("初始化年龄:"+age);
}
public int GetAge(int age){
this.age = age;
return this.age;
}
}
public class test1 {
public static void main(String[] args) {
Person Harry = new Person();
System.out.println("Harry's age is "+Harry.GetAge(12));
}
}
3.引用构造函数
7.2 super
super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。super 也有三种用法:
1.普通的直接引用,与 this 类似,super 相当于是指向当前对象的父类,这样就可以用 super.xxx 来引用父类的成员。
2.子类中的成员变量或方法与父类中的成员变量或方法同名
class Country {
String name;
void value() {
name = "China";
}
}
class City extends Country {
String name;
void value() {
name = "Shanghai";
super.value(); //调用父类的方法
System.out.println(name);
System.out.println(super.name);
}
public static void main(String[] args) {
City c=new City();
c.value();
}
}
//运行结果:
//Shanghai
//China
3.引用构造函数
- super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
- this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。
class Person {
public static void prt(String s) {
System.out.println(s);
}
Person() {
prt("父类·无参数构造方法: "+"A Person.");
}//构造方法(1)
Person(String name) {
prt("父类·含一个参数的构造方法: "+"A person's name is " + name);
}//构造方法(2)
}
public class Chinese extends Person {
Chinese() {
super(); // 调用父类构造方法(1)
prt("子类·调用父类"无参数构造方法": "+"A chinese coder.");
}
Chinese(String name) {
super(name);// 调用父类具有相同形参的构造方法(2)
prt("子类·调用父类"含一个参数的构造方法": "+"his name is " + name);
}
Chinese(String name, int age) {
this(name);// 调用具有相同形参的构造方法(3)
prt("子类:调用子类具有相同形参的构造方法:his age is " + age);
}
public static void main(String[] args) {
Chinese cn = new Chinese();
cn = new Chinese("codersai");
cn = new Chinese("codersai", 18);
}
}
/*运行结果:
父类·无参数构造方法: A Person.
子类·调用父类”无参数构造方法“: A chinese coder.
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
子类:调用子类具有相同形参的构造方法:his age is 18*/
可以用 super 和 this 分别调用父类的构造方法和本类中其他形式的构造方法。例子中 Chinese 类第三种构造方法调用的是本类中第二种构造方法,而第二种构造方法是调用父类的,因此也要先调用父类的构造方法,再调用本类中第二种,最后是重写第三种构造方法。
8、枚举类型,枚举一个类型枚举 CategoryEnum.java 设置属性:FRUIT、CLOTHES、PHONE、BOOKS
public enum CategoryEnum {
FRUIT("orange","01"),
CLOTHES("T-shirt","02"),
PHONE("Huawei","03"),
BOOKS("The Story of My Uncle","04");
private String name;
private String id;
CategoryEnum(String name, String id) {
this.name = name;
this.id = id;
}
@Override
public String toString() {
return this.id + "_" + this.name;
}
}