JavaSE04
博主学习视频:b站狂神说Java
有参构造与无参构造
alt + insert 打开生成
点击构造函数,(确定)生成有参,(select none)生成无参
- 与类名相同
- 没有返回值
public class Man {
String name;
int age;
//实例化初始值
//1.使用new关键字,本质是在调用构造器
//2.用来初始化值
public Man(){ //Man类中即使什么都不写,也会存在这样的一个方法
} //默认的构造方法: 无参构造
//有参构造:一旦定义了有参构造,无参构造就必须显示定义,否则没有默认无参构造
public Man(String name){
this.name=name;
}
public Man(String name, int age) {
this.name = name;
this.age = age;
}
}
创建对象内存分析
对象是通过引用来操作的:栈(存放内存地址)—>堆(实际储存位置)
封装
***”高内聚,低耦合“***:
- 高内聚:类的内部数据操作细节独立完成,不允许外部干涉
- 低耦合:仅暴露少量的方法给外部使用
封装(数据的隐藏):应禁止直接访问一个对象中数据的实际表示,应通过操作接口来访问,即信息隐藏。
属性私有 | get /set |
---|---|
private String name; | public String getName(){return this.name;} |
public void setName(String name) {this.name = name;} |
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age <= 120 && age >= 0) {
this.age = age;
}else{
System.out.println("击穿2021人类寿命上下限");
}
} //封装时可以进行安全写入
封装的意义:
- 提高程序安全性,保护数据
- 隐藏代码的设计细节
- 统一接口
- 提高了程序的可维护性
继承
extends:意为”扩展“,子类是对父类的拓展。
Java中只有单继承,没有多继承。
子类继承了父类,就会拥有父类的除private方法。
public | protected | default | private |
---|---|---|---|
权限最高 | 权限最低 |
Java中所有的类都默认直接或间接继承Object类
super
//父类
public class Person {
protected String name = "qq";
}
//派生类,子类
public class Student extends Person{
private String name = "ww";
public void test (String name){
System.out.println(name); //指代的是形参name;输出ee
System.out.println(this.name); //指代的是Student类的属性name;输出ww
System.out.println(super.name); //指代的是父类Person的属性name;输出qq
}
}
//主方法
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test("ee");
}
}
super注意点:
- 使用super调用父类的构造方法,必须在子类构造方法的第一行。(默认)
- super只能出现在子类的方法或者构造方法中。
- super和this不能同时调用构造方法
super | this | |
---|---|---|
代表的对象 | 父类对象的引用 | 自身调用者这个对象 |
使用前提 | 有继承才能使用 | 无需继承 |
构造方法 | super( ):父类的构造 | this( ):本类的构造 |
方法重写
父类B:
public class B {
public static void test() {
System.out.println("B.test");
}
}
子类A:
public class A extends B{
public static void test() {
System.out.println("A.test");
}
}
public class Application {
public static void main(String[] args) {
A a = new A();
a.test(); //输出A.test
//父类的引用指向了子类
B b = new A();
b.test(); //输出B.test
}
}
静态的方法和非静态的方法区别:
-
静态方法:方法的调用只和定义的类型有关
-
非静态方法:
B b = new A();//子类重写了父类的方法 b.test(); //输出A.test
重写:需要有继承关系,子类重写父类的方法(用于缩减或补充),属性没有重写
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小 public>protected>default>private
- 抛出的异常:范围可以被缩小,但不能扩大
重写快捷键:alt+insert—>重写
多态
多态可以实现动态编译。
父类Person
public class Person {
public void run(){
System.out.println("run");
}
}
子类Student
public class Student extends Person{
@Override
public void run() {
System.out.println("student");
}
public void eat() {
System.out.println("eating");
}
}
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//指向的引用类型不确定:父类的引用指向子类的对象
//Student 可以调用本身与继承父类的方法
Student s1 = new Student();
//Person 父类,可以指向子类,但不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
s1.run();//run
//子类重写了父类的方法,执行子类的方法
s2.run();//student
s1.eat();
//父类类型没有子类独有的方法,需要强制类型转换
((Student) s2).eat();
}
}
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类,需要继承关系 不然有”类型转换异常“(ClassCastException)
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象
没有多态的状况:
- static 方法,属于类,它不属于实例;
- final 常量;
- private 方法,私有方法无法重写;
instanceof
instanceof可以用于判断两个类中间是否存在父子关系
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
System.out.println(object instanceof Student); //true
System.out.println(object instanceof Person); //true
System.out.println(object instanceof Object); //true
System.out.println(object instanceof Teacher); //false
System.out.println(object instanceof String); //false
Person person = new Student();
System.out.println(person instanceof Student); //true
System.out.println(person instanceof Person); //true
System.out.println(person instanceof Object); //true
System.out.println(person instanceof Teacher); //false
//System.out.println(person instanceof String); //编译报错
Student student = new Student();
System.out.println(student instanceof Student); //true
System.out.println(student instanceof Person); //true
System.out.println(student instanceof Object); //true
//System.out.println(student instanceof Teacher);//编译报错
//System.out.println(student instanceof String); //编译报错
(X instanceof Y)式子会不会报错主要取决与X与Y直接是否有继承关系,类似于
中国>广东>深圳
中国>广东>广州
中国>台湾
报错:广东 instanceof 台湾
广州 instanceof 台湾
广州 instanceof 深圳
//类型之间的转换:
//Object > Person > Student
//Person's run()
//Student's go()
//高类型(父类) 低类型(子类)
Person man = new Student();
((Student) man).go();
//子类类型 转换为 父类类型,可能会丢失一些方法
Student woman = new Student();
woman.go();
//((Person)woman).go();//报错
instanceof事项:
- 父类引用指向子类对象
- 子类转换为父类,为向上转型,不需强制转换
- 父类转换为子类,为向下转型,需要强制转换,可能会丢失方法
- 方便方法的调用,减少重复的代码
static关键字
静态的可以直接使用:
静态变量对于类而言,在内存中只有一个,能被类中所有实例所共享
静态方法同类一起加载,可以直接在同类方法中使用
静态代码块同类一起加载直接指向,且只执行一次
执行顺序:
静态代码块>匿名代码块>构造方法>main方法
匿名代码块和对象同时产生,每生成一个新对象,执行一次,可用于赋初始值
static {
System.out.println("静态代码块");
}
{
System.out.println("匿名代码块");
}
//静态导入包
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
// 正常用法
// System.out.println(Math.random());
System.out.println(random());
}
}
使用final修饰的类无法使用继承机制
抽象类
//abstract 抽象类
public abstract class Action {
//abstract 抽象方法,只有方法名字,没有方法的实现
public abstract void doSomething();
}
//对于抽象类的所有方法,继承了抽象类的子类(非抽象类),都必须要实现这些方法
public class A extends Action{
@Override
public void doSomething() { }
}
抽象类的注意事项:
- 抽象类不能通过new来实例化,只能靠子类去实现它,本质上是一个约束
- 抽象类中可以写普通方法
- 抽象方法必须在抽象类中
抽象类存在构造器,Java中抽象类的构造器的作用_YoaMy的博客-CSDN博客_抽象类构造方法作用
1. 因为抽象类不能实例化对象,所以必须要有子类来实现它之后才能使用。这样就可以把一些具有相同属性和方法的组件进行抽象,这样更有利于代码和程序的维护。
2. 当又有一个具有相似的组件产生时,只需要实现该抽象类就可以获得该抽象类的那些属性和方法。
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法) 都有
-
接口:只有规范(抽象方法) ,本身无法写方法
专业的约束:完成约束与实现的分离:面向接口编程doge~
接口就是规范,定义的是一组规则,就像现实中的“如何你是鱼,那你必不可能被淹死”。
//接口UserService
//声明的关键词是interface,且接口都需要有实现类
public interface UserService {
//接口中的所有定义都是抽象的,而且是public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//接口TimeService
public interface TimeService {
void timer();
}
//抽象类:通过extends实现
//类可以通过implements来实现接口
//实现了接口的类就需要重写接口中的方法
//接口可以多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {}
@Override
public void delete(String name) {}
@Override
public void update(String name) {}
@Override
public void query(String name) {}
@Override
public void timer() {}
}
接口中定义的属性默认是public static final,是一个常量。
接口的作用:
1. 约束
2. 定义一些方法,允许群体开发
3. 接口中定义的方法是public abstract,定义的属性是public static final
4. 接口不能被实例化,且没有构造方法
5. implements可以实现多个接口
6. 必须要重写接口中的方法
内部类
//主类
public class Outer {
private int id;
public void out() {
System.out.println("外部类");
}
class Inner{
public void in(){
System.out.println("内部类");
}
//获得主类的私有属性
public void getID(){
System.out.println(id);
}
}
public static class inn{
public void getID(){
//报错,static属性和主类一起加载,此时不存在private属性的id
//因而无法访问非静态的属性
System.out.println(id);
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
一个.java文件中可以有多个class类,但是只能有一个public class
public class Outer {
}
class A{
}
class B{
}
public class Outer {
//局部内部类
public void method() {
class Inner {
public void in(){}
}
}
}
神奇的写法,头疼,学的有点消化不良了
public class Test {
public static void main(String[] args) {
new Apple().eat();
//匿名内部类
UserService userService = new UserService(){
@Override
public void hello() { }
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}