1.类和对象
类是具有共同属性,共同方法的一类事物。
对象是该类事物的个体。
对象的抽象化是类,类的具体化是对象。
上述代码中,Person是同一个类,Test类中main函数中的person是一个Person类的对象,这个对象的name属性为张三。
1.1定义类
java类名必须是一个或多个有意义的单词连缀而成,每个单词首字母大写,其他小写。单词与单词之间没有分隔符。
类的五种成员:
构造器,成员变量,方法,初始化块,内部类。
常见的三种成员:
构造器,成员变量,方法。
访问修饰符
分类
- private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
- public : 对所有类可见。使用对象:类、接口、变量、方法
一般情况下,使用protected来修饰一个方法,通常是希望子类来重写这个方法。
1.2构造器
构造器在创建对象时执行初始化。在系统开始执行构造器之前,系统已经创建了一个对象,这个对象只能在该构造器中通过this执行。
构造器中使用另一个构造器this(参数),而且this()必须要作为构造器执行的第一条语句。
[修饰符] 构造器名(形参列表){
}
public class Person {
public Person() {
}
}
public class Person {
private int num;
public Person(int num) {
this.num = num;
}
}
构造器的作用:
- 创建对象
- 初始化成员变量
构造器的特点:
- 构造方法的方法名要与类名一致
- 构造方法无返回类型,void类型也不可以
- 构造方法分为:有参构造方法和无参构造方法
- 构造方法是不能被继承的,但是可以使用super来调用,且super必须声明在在子类构造方法中的首行
- 默认有一个无参构造方法,当自定义无参构造方法的时候,默认则无效
- 可以没有构造方法(编译器默认有一个无参构造方法),也可以有多个构造方法,他们之间构成重载关系
1.3初始化块
[修饰符]{
}
有static 类初始化块(静态初始化块)
无static 实例初始化块(非静态初始化块)
实例化初始化块只在创建java对象时隐式执行。
类例化初始化块在创建类对象时隐式执行。
1.4 static关键字
static是一个特殊的关键字,它可用于修饰方法,成员变量等成员,static修饰的成员表明它属于这个类本省,而不属于该类的单个实例。所以static修饰的成员变量,方法又称为类变量,类方法,也称为静态变量,静态方法。
public class Person {
public static int money;
}
public class Test {
public static void main(String[] args) {
Person.money = 1;
new Person().money = 2;
}
}
对于static修饰的成员变量和方法都可以通过类或者对象来调用,但是建议是使用类来调用类成员和类变量。因为static修饰的成员不属于该类的单个实例。
static修饰的成员不能访问没有static修饰的成员。
1.5 对象的this引用
this作为对象的默认引用有两种情况
- 构造器中引用构造器正在初始化的对象。
- 在方法中引用调用该方法的对象。
public class Person {
private int num;
public Person(int num) {
//这里的this是构造器正在初始化的对象。
this.num = num;
}
public void show(){
//这里的this是调用该方法的person对象
System.out.println(this.num);
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person(10);
person.show();
}
}
static修饰的方法中不能使用this引用。
如果在某个方法中把this作为返回值,则可以多次连续调用同一个方法,但是可能造成实际意义的模糊。
1.6方法
方法要使用this或者类来作为调用者,使用static修饰的方法既可以使用类来作为调用者,也可以使用对象来作为调用者。
1.6.1方法中的参数传递
java中的方法的参数传递只有值传递。
但是当传参作为一个对象时,传入的是一个引用传递。所以传参是对象的时候,对象的属性值可以被改变。但是如果传参是基本类型的值,原本的值是不会改变的。
public class Test {
public static void main(String[] args) {
Person person = new Person(10);
change(person);
//输出为9
person.show();
}
public static void change(Person person){
person.setNum(9);
}
}
1.6.2方法重载
方法重载是一项功能,如果一个类的参数列表不同,则它允许一个类拥有多个具有相同名称的方法。
重载两同一不同:
同一个类中方法名相同,参数列表不同。
详解:Java的重载方法与示例_方法的重载的实例__陈哈哈的博客-CSDN博客
1.7 成员变量和局部变量
成员变量是在类中定义的变量,局部变量是在方法中定义的。
只要为一个类定义了类变量或者实例变量,系统会在这个类的准备阶段或创建类的实例时进行默认初始化。
java允许局部变量和成员变量同名,如果同名,局部变量会覆盖成员变量,如果要用成员变量,可以使用this或类名。
局部变量定义之后,必须要经过显式初始化才能使用。
1.8 包package import和import static
package:
包名全部为小写字母,由一个或者多个单词连缀而成,包在电脑中是文件夹的形式。
import:
可以导入指定包下的某个类或者全部类。
import语句中的(*)只能代表类,不能代表包。
//引入util包下List类
import java.util.List;
//引入util包下所有类
import java.util.*;
import static:
用于导入指定类型的单个静态成员变量,方法和全部静态成员变量,方法。
import static语句中的(*)代表指定类下所有的全部静态成员变量,方法。
import static chat.view.enter.DeleteGroupController.*;
import static chat.view.enter.MessageController.clientService;
2.面向对象的三种基本特征
封装,继承和多态。
2.1封装
封装是指将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能。即将对象的状态信息隐藏在对象内部,不允许外部查询直接访问对象的内部信息,而是通过该类所提供的方法来对内部对象的操作和访问。
封装的步骤:
- 将对象的成员变量和实现细节隐藏起来,不允许外部直接访问。
- 将方法暴露出来,让方法来控制对这些成员变量来进行安全的访问和操作。
public class Person {
private int num;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
封装的作用:
提高了类的内聚性,降低了对象之间的耦合性。
高内聚:尽可能把模块的内部数据,功能实现细节隐藏在模块内部完成,不允许外部自己干预。
低耦合:仅暴露少量的方法给外部使用。
2.2继承
继承是面向对象实现软件复用的重要手段,当子类继承父类之后。子类作为一种特殊的父类,将直接获得父类的属性和方法。
java中的继承只允许单继承。每个子类只有一个直接父类。
父类派生了子类,子类是父类的扩展,子类可以获得父类的全部成员变量,方法和内部类,但是子类不能获得父类的构造器。
2.2.1 重写父类的方法
子类包含与父类同名方法的现象被称为方法重写。(方法覆盖)
方法的重写(两同两小一大):
- 方法名相同,形参列表相同。
- 子类方法返回值类型应比父类方法返回值类型更小或者相等。
- 子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或者相等。
- 子类方法的访问权限应比父类方法的访问权更大或者相等。
覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法。
父类方法是private访问权限,则无法访问或者重写。
public class Person {
public void show(){
System.out.println("被覆盖的方法");
}
}
public class A extends Person{
public void show(){
System.out.println("覆盖方法");
}
public static void main(String[] args) {
//覆盖方法
new A().show();
}
}
2.2.2 super
需要在子类方法中调用父类被覆盖的实例方法,可用super();
super用于限定该对象调用它从父类继承得到的实例变量或方法(构造器和方法)。
在构造器中使用super()继承父类的构造器,必须把super()放在构造器的第一句。
创建如何对象总是从所在继承树最顶层类的构造器开始执行,然后依次向下执行。
public class A extends Person{
public void show(){
super.show();
System.out.println("覆盖方法");
}
public static void main(String[] args) {
//被覆盖的方法
//覆盖方法
new A().show();
}
}
2.3多态
概念:多态是子类对象可以直接赋值给父类变量,但运行时依然表现出子类的行为特征,这意味着同一个类型的对象在运行同一个方法时,可以表现出多种行为特征。
java引用变量有两种类型,一个是编译类型,一个是运行时类型。如果编译时类型和运行时类型不一致,就是多态。
public static void main(String[] args) {
Person person = new A();
}
Person是父类,A是子类,编译时是Person类型,运行时A类型。
当调用被重写的方法的时候,执行的是子类重写后的方法,这里就体现出了多态。
public static void main(String[] args) {
Person person = new A();
//覆盖方法
person.show();
}
上面类型转换被称为向上转型,把一个子类对象直接赋给一个父类引用变量。
与方法不同的是,对象的实例变量是不具备多态性的。
引用类型的强制类型转换
(type) variable
- 基本类型之间的强制类型转换只能在数值类型之间进行。
- 引用类型之间的转换只能在具有继承关系的两个类型之间进行。
考虑到强制类型转换会产生异常,,要先用instanceof判断,instanceof运算符前面的操作数的编译类型要么与后面的类型相同,要么具有父子继承关系。
public static void main(String[] args) {
Double d = 0.1;
if(d instanceof Double){
System.out.println("true");
}
}
public static void main(String[] args) {
//输出true
A p = new A();
if(p instanceof Person){
System.out.println("true");
}
}
2.3.1继承和组合
继承和组合的区别_组合和继承的区别_Howard_14的博客-CSDN博客
继承是实现类复用的重要手段,但继承的坏处是:破坏封装。
继承可以访问父类的成员变量和方法,并可以改变父类方法的实现细节。但是组合不会。
组合也是实现类复用的重要手段,但组合能提供更好的封装性。
组合是把旧类对象作为新类的成员变量组合起来,用来实现新类的功能。
/**
* 动物
*/
public class Animal {
public void breathing() {
System.out.println("呼气...吸气...");
}
}
/**
* 爬行动物
* 组合
*/
public class Reptilia {
private Animal animal;
public Reptilia(Animal animal) {
this.animal = animal;
}
public void crawling() {
System.out.println("爬行...");
}
public void breathing() {
animal.breathing();
}
public static void main(String[] args) {
Animal animal = new Animal();
Reptilia reptilia = new Reptilia(animal);
reptilia.breathing();;
reptilia.crawling();
}
}
3 包装类
基本数据类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | .Double |
boolean | Boolean |
char | Character |
包装类可以把8个基本类型的值包装成对象引用。
jdk1.5之后提供了自动装箱和自动拆箱功能,允许把基本类型值直接赋给对应的包装类引用变量,也允许把包装类对象赋给对应的基本类型变量。
什么是自动装箱和自动拆箱?
- 自动装箱:基本数据类型自动转换成包装类。
- 自动拆箱:包装类自动转换成基本数据类型。
包装类与字符串之间的转换
4常见方法
toString()
toString()是Object类中的一个实例方法,所有的java对象都具有toString()方法,这个方法是对象的自我描述方法。
“==”和equals()
如果两个变量是基本数值类型变量,则是判断两个变量只是否相等。
如果两个变量是引用类型变量,只有它们指向的是同一个对象的时候,返回值才是true。
但是要注意的是String类重写了equals(),String类的equals()比较的是两个字符串的值。
public static void main(String[] args) {
String a = new String("hello");
}
这里要注意的是new String("hello"),JVM会先使用常量池来管理"hello"直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中,所以new String("
hello")创建了两个新字符串对象。
5 final
final修饰的类,方法和变量不可改变。该变量一旦获得初始值就不可改变。
final成员变量
成员变量的初始值可以在定义该变量时指定默认值,也可以在初始化块,构造器中指定初始值。
java中规定:final修饰的成员变量必须有程序员显式指定初始值。
final局部变量
final修饰的局部变量必须有程序员显式指定初始值。可以在定义的时候指定,也可以不在。局=基本类型变量不能改变。
final保存的仅仅只是一个引用,final值保证这个引用类型变量所引用的地址不会改变,但是这个对象可以改变。
final方法
final方法不可重写。
使用final修饰一个private访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名,相同形参列表,相同返回值类型的方法。
final类
final类不能有子类。
6 抽象类
抽象方法和抽象类必须使用abstract修饰符来定义。
抽象方法的 3 个特征如下:
- 抽象方法没有方法体
- 抽象方法必须存在于抽象类中
- 子类重写父类时,必须重写父类所有的抽象方法
abstract class A{
public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
}
abstract不能与static同时修饰某个方法。
abstract不能与private同时修饰方法。
抽象类的作用
抽象类不能创建实例,只能被当做父类被继承。
抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展,改造。
抽象类
7 接口
接口定义了一种规范,只规定这批类里必须提供某些方法。
public interface Person{
}
一个接口可以有多个直接符父接口,但是接口只能继承接口,不能继承类。
接口:
(1)成员变量(静态变量)public static final
(2) 方法(抽象实例方法[public abstract],类方法[public static],默认方法[default] 私有方法)
(3)内部类(内部接口,枚举)
类使用implements实现接口,必须完全实现接口中所定义的抽象方法。
抽象类和接口的区别
接口与抽象类的相似点
(1) 接口和抽象类都不能被实例化,都可以被其他类实现和继承。
(2) 接口和抽象类都可以包含抽象方法。实现接口或继承抽象类的普通子类都必须实现这些抽象方法。
区别
(1)接口里只能包含抽象方法,静态方法和默认方法(加default),不能为普通方法提供方法实现,抽象类则完全可以包含普通方法,接口中的普通方法默认为抽象方法。
(2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的,并且必须赋值。
(3)接口不能包含构造器,抽象类可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
(4)接口里不能包含初始化块,但抽象类里完全可以包含初始化块。
(5)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
8 枚举类
public enum SeasonEnum {
SPRING,SUMMER,FALL,WINTER;
}