JAVA 基础 面向对象
什么是成员变量、局部变量、静态变量
成员变量
- 成员变量 定义在类中, 在整个类中都可以被访问到
- 成员变量随着对象的建立而建立, 随着对象的消失而消失
- 成员变量有默认初始化值
示例
class Car{
private String name; // 成员变量
private String color; // 成员变量
}
局部变量
- 局部变量只定义在局部范围内, 如:函数、 语句内 , 只在所属的区域有效
- 局部变量存在于栈内存中, 作用的范围结束, 变量空间会自动释放
- 局部变量没有默认初始化值
示例
class Car{
public void main(String[] args){
Integer sum = 0; // 局部变量
for (int i = 0; i < 10; i++) { // 这里的i 也是局部变量
sum += i;
}
System.out.println(sum);
}
}
静态变量
- 由
static
修饰的变量成为静态变量, 其 实质上就是一个全局变量。 如果某个内容是被所有对象所共享,那么该内容就应该用静态修饰; 没有被静态修饰的内容,其实就是对象的特殊描述。
示例
class Person{
// 成员变量, 实例变量
String name;
// 静态变量, 类变量
static String COUNTRY = "CN";
}
成员变量和静态变量的区别
- 两个变量的生命周期不同
- 成员变量随着对象的创建而存在,随着对象的回收而释放
- 静态变量随着类的加载而存在, 随着类的消失而消失
- 调用方式不同
- 成员变量只能被对象调用
- 静态变量可以被对象调用,还可以被类名调用
- 别名不同
- 成员变量也称为 实例变量
- 静态变量也称为 类变量
- 数据存储位置不同
- 成员变量存储在堆内存的对象中,也叫做对象的特有数据
- 静态变量存储在方法区(共享数据区)的静态区, 所以也叫做对象的共享数据
##访问修饰符
一句话 private 和 public
private 仅可以在 类内部使用
public 可以在任意地方使用
构造方法
当new
一个对象的时候 其实就是在调用构造方法,当没有定义构造方法的时候, Java 会默认提供一个无参的构造方法
例如
class Student{
// 这时就会默认提供一个无参的构造方法
/*
public Student(){} // 构造方法的名字必须和类名相同, 并且不需要提供返回值
*/
}
通过构造方法初始化参数
class Student{
private String name;
private Integer age;
public Student(){}
public Student(String name){
this.name = name;
}
public Student(String name, Integer age){
this.name = name;
this.age = age;
}
public static void main(String[] args){
new Student("CharmNight", 21);
new Student("CharmNight");
new Student();
}
}
通过上面的方法也可以看出 构造方法 可以有多个
this 关键字
this
关键字只能在类中使用, 代表当前对象。
示例一: 通过this区分成员变量 用于赋值
class Student{
private String name;
private Integer age;
public Student(String name){
// 这里就是使用 this 区分成员变量和参数
// this. 来访问成员变量 直接访问的是参数
this.name = name;
}
}
示例二: 通过this访问成员方法
class Student{
private String name;
private void cheat(){
System.out.println("考试作弊");
}
public void examination(){
this.cheat();
}
}
静态
static
关键字
含义
Java中不存在真正意义上的全局变量,但是可以通过static
来实现一个“伪全局”的概念,在Java中static
表示全局 或者 静态的意思, 用来修饰成员变量和成员方法, 也可以修饰代码块.
Java把内存分为堆内存和栈内存,其中栈内存用来存放一些基本类型的变量、数组和对象的引用。
堆内存主要存放一些对象。JVM
加载一个类的时候,若该类存在static
修饰的成员变量和成员方法,则会为这些成员变量和方法 在固定的位置开辟一个固定大小的内存区域.
同时被static
修饰的成员变量和成员方法是独立该类的,它不依赖于某个特定的实例变量,也就是说它被该类的所有实例共享。所有实例的引用都指向同一个地方,任何一个实例对其进行修改都会导致其他实例的变化。
例子
public class Person {
public static String country;// 静态变量
private String name;
private int age;
Person(String name, int age){
this.age = age;
this.name = name;
}
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 static void show(){
// 静态方法中 只能调用 静态的 方法 or 变量
// 且 不能使用 this super 关键字
System.out.println(country);
}
}
class PersonTest{
public static void main(String[] args) {
Person p1 = new Person("siki", 10);
p1.country = "CN"; // 一般使用 Person.country = "CN"
Person p2 = new Person("Peter", 20);
p2.country = "US"; // Person.country = "US"
System.out.println(p1.getName() + p1.getAge() + p1.country);
System.out.println(p2.getName() + p2.getAge() + p2.country);
}
}
------输出结果-----
siki10US
Peter20US
static
占内存
static 修饰的变量 会在 类加载时在 方法区(共享)的静态区中开辟一块内存进行存储
static 是和类进行绑定的
###static
特点
- 随着类的加载而加载
- 优先于对象存在
- 所有对象共享(可以通过对象或类来访问)
局限性
- 只能调用
static
变量和static
方法 - 不能以任何形式引用
this
、`super
总结
无论是变量,方法,还是代码块,只要被static
修饰,就在类被加载的时候被创建
静态代码块
static{
// 这里就是静态代码块 在加载类时 仅执行一次
}
示例
public class StaticDemo {
static float pi;
static {
pi = 3.14F;
System.out.println("静态代码块执行");
}
StaticDemo(){
System.out.println("构造函数执行");
}
public static void main(String[] args) {
new StaticDemo();
new StaticDemo();
}
}
------打印结果-------
静态代码块执行
构造函数执行
构造函数执行
封装
数据私有化 private
,但不止这一个状态 应该说除了public
都是封装的思想,
除了private
类
、 方法
这些都属于封装的思想
优点
- 良好的封装能减少耦合
- 类内部的结构可以自由的改变
- 可以对成员进行更精确的控制
- 隐藏信息,实现细节
更精确的控制成员
防止 属性被随意修改
class Student{
public String name;
public Student(){
this.name = "CharmNight";
}
}
class StudentTest{
public void main(String[] args){
Student st = new Student();
// xxx 一顿操作
st.name = "hh"; //?? 误修改
}
}
GET SET 方法
class Student{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
class StudentTest{
public void main(String[] args){
Student st = new Student();
// 通过 get set 方法 来 获取 修改 私有变量
st.setName("CharmNight");
st.getName();
}
}
隐藏信息,实现细节
class Phone{
private String cpu;
private String color;
private Boolean power;
public Phone(){
this.power = false;
}
private void phoneInnerShutDown(){
// 手机内部关机逻辑
this.color = "black";
this.cpu = "down";
this.power = false;
}
private void phoneInnerBoot(){
// 手机内部开机逻辑
this.color ="color";
this.cpu = "on";
this.power = true;
}
public void run(){
// 傻瓜式 按电源开机 or 关机
if(this.power){
this.phoneInnerShutDown();
}else{
this.phoneInnerBoot();
}
}
}
class phoneTest{
public static void main(String[] args){
Phone phone = new Phone();
phone.run(); // 开机了 可以愉快的玩耍了
}
}
良好的封装能减少耦合
类内部的结构可以自由的改变
内部类
class Outer{
private int age;
public Outer(int age){
this.age = age;
}
private class Inner{
private String name;
public Inner(String name){
this.name = name;
}
public void show(){
System.out.println(this.name);
}
}
public void test(){
Inner inner = new Inner("innerClass");
inner.show();
}
public static void main(String[] args) {
Outer outer = new Outer(12);
outer.test();
}
}
注意事项
- 内部类不能声明
static
- 内部类可以访问外部类的成员变量, 外部类不可访问内部类的成员变量
继承
概念
- 继承就是子类继承父类的行为。
- 继承是一种代码复用。
- 继承 所描述的是 “is-a” 的关系 , 如果有两个对象A和B, 若可以描述为 A是B 则可以表示A继承B,其中B是被继承者 被称之为父类 或者 超类,A是继承者 称之为子类或者派生类
注意
-
子类拥有父类非
private
的属性和方法 -
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展
-
子类可以用自己的方式实现父类的方法
-
子类和父类梨有同名变量,就近原则(this super)
可以通过super 访问父类梨的变量、方法和构造方法
例子
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
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 class Student extends Person {
private String className;
public Student(String name, int age, String className) {
super(name, age);
this.className = className;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
优点
- 减少了代码量
- 代码更容易维护
Java不支持多继承
重载
类名相同,但参数不同,返回值可以相同也可以不同
规则
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
重写
子类中的方法名、参数和返回值与父类相同
意义
子类跟父类拥有同样的功能,但是子类有自己的特定内容和特定实现方式。可以定义一个不同的名字方法,但是为了见名知意,保持父类的名字,自己重新实现方法体
注意事项
- 不能重写
private
方法 - 不能重写
final
的方法 - 不能重写
static
方法 但可以再次声明 - 重写的时候,访问权限不能变更
多态
定义
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作
允许不同类的对象对同一消息作出响应
作用
消除类型之间的耦合关系
实现方式
- 重写
- 接口
- 抽象类抽象方法
class Person{
}
class Student extend Person{
}
class Test{
public static void main(String[] args){
Person p = new Student(); // 多态
}
}
抽象
抽象类
定义
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
例子
abstract class Person{
private String name;
public Person(String name){
this.name = name;
}
public abstract void eat();
public void run(){
System.out.println("跑路");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Student extends Person{
public Student(String name) {
super(name);
}
public void eat() {
System.out.println("吃");
}
}
public class absDemo {
public static void main(String[] args) {
Person p = new Student("Night");
System.out.println(p.getName());
p.eat();
p.run();
}
}
接口
定义
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
接口与类相似点:
- 一个接口可以有多个方法。
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
- 接口的字节码文件保存在 .class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
接口特性
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
抽象类和接口的区别
-
抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
-
抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
-
接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
-
一个类只能继承一个抽象类,而一个类却可以实现多个接口。
例子
public interface USB{
public Integer USB3();
}