Java类与对象,Scanner,编码体系

类与对象

  1. java中有两个地方具有默认初始化,数组,类的成员变量
  2. java中以包作为默认管理级别,那默认情况下同一个包中都可以访问
  3. public private default辨析:
访问权限 本类 本包的类 子类 非子类的外包类
public
protected
default
private

1、public: 所修饰的类、变量、方法,在内外包均具有访问权限;
2、protected: 这种权限是为继承而设计的,protected所修饰的成员,对所有子类是可访问的,但只对同包的类是可访问的,对外包的非子类是不可以访问;
3、包访问权限(default): 只对同包的类具有访问的权限,外包的所有类都不能访问;
4、private: 私有的权限,只对本类的方法可以使用;


构造方法:
1).构造方法的定义

它具有与类相同的名称;

它不含返回值;

注意:在构造方法里不含返回值的概念是不同于“void”的,在定义构造方法时加了“void”,结果这个方法就不再被自动调了。

2).构造方法的作用

当一个类的实例对象刚产生时,这个类的构造方法就会被自动调用,我们可以在这个方法中加入要完成初始化工作的代码。这就好像我们规定每个“人”一出生就必须先洗澡,

我们就可以在“人”的构造方法中加入完成“洗澡”的程序代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们要“洗澡”了。

语法格式:

< 修饰符>  <类名>([< 参数表>]) {

     [< 语句>]

}
public class Animal {
private int legs;
public Animal() {
  legs = 4;
}    //构造器
public void setLegs(int i) {
  legs = i;
}
public int getLegs(){
  return legs;
}
}
//创建Animal类的实例:Animal  a=new Animal(); //调用构造器,将legs初始化为4.

3).默认的构造方法

Java语言中,每个类都至少有一个构造方法;

如果类的定义者没有显式的定义任何构造方法,系统将自动提供一个默认的构造方法:

–默认构造方法没有参数

–默认构造方法没有方法体

–默认的构造方法:Animal(){ }

所以:不编写构造方法就能用new Xxx()创建类的实例。

Java类中,一旦类的定义者显式定义了一个或多个构造方法,系统将不再提供默认的构造方法;

4).构造方法重载

构造方法重载使得对象的创建更加灵活,方便创建各种不同的对象。

构造方法重载举例:

public class Person{
    public Person(String name, int age, Date d) {this(name,age);}
    public Person(String name, int age) {}
    public Person(String name, Date d) {}
    public Person(){}
}

构造方法重载,参数列表必须不同

类的封装

  1. 对于新建的类 要封装他 需要在类中的变量的权限改为private 然后对其添加get和set方法
  2. 在写get和set方法时,方法中的参数要顾名思义,不能随便乱写
  3. bool类型的getter不能用setXXX(),而是要用isXXX()。bool类型取名尽量不要添加is作为开头,因为generator会自动将bool类型的变量的方法命名为isXXX(),容易撞名字。
  4. 对于除了bool类型之外的其他类型,第二个字母最好不要大写。原因同上。

构造方法

  1. 构造方法分为无参构造,有参构造,全参构造
  2. 实例化类的时候,就会进行构造方法的调用。
  3. 构造方法是不能写返回值的
  4. 类的构造方法,默认是无参构造,当类中未声明任何构造方法时,才会具备默认的无参构造。
  5. this关键字
    1. 引用当前对象
    2. 本类中调用构造方法
  6. 普通方法,也叫实例方法,它的执行必须依赖对象。
  7. 可以通过构造方法创建对象,通过关键字new来调用构造方法。
  8. 可以多多使用.var这个小技巧 实例化时会更方便。
  9. 直接用new 例:
new Person().say();
这是一个匿名对象。不持有对方的引用。
  1. 构造方法的方法名固定,与类名一致。
  2. 构造方法,不能声明返回值,但是它的本质上是有返回值的,返回类的对象的实例
  3. 任何类都必须具有构造方法。当代码中未声明任何构造方法,则有一个著名的默认无参构造,是public级别的。
  4. 编写类的时候不要吝啬this关键字的使用
  5. 构造方法之间的调用:
    1. 通过this()来调用本类的构造方法,必须放置首行,而且只能有一个(因为如果有多个,就是相当于实例化了多个类的实例)
    2. 调用有参构造,只能调用一次,只要调用一次就会产生一个新的对象。
    3. 构造方法的调用,类内用this();,类外用new。

方法的重载

  1. 一个类中的不一样的方法,恰好方法名相同,签名不同。
  2. 方法签名: 就是方法名和方法的参数列表。java不允许有相同的方法签名出现。
    example:
say(){
    sout("?);
}
say(String str){
    sout(str);
}

静态

  1. 若要直接在类中调用方法,可以给方法添加static关键字,使其变为静态方法,就可以进行直接调用了,不用实例化再调用。
  2. 静态方法与类行管,它的执行只需要类名,不需要对象。
  3. 不加static就是实例方法 实例方法的执行依赖对象。
  4. 就算是初始化为空的类也可以使用静态方法。即null在代码上可以调用静态方法
  5. 比如就算使用了dog.fn1();,编译之后还是会编译成Dog.fn1();fn1是Dog中的静态方法
  6. 静态方法和实例方法之间的调用关系:静态方法不允许调用实例方法,反之可以。
  7. static和this关键字水火不容 因为this代表当前对象

代码块

  1. 初始化对象时,先执行静态代码块,再执行实例代码块,最后执行构造方法。
  2. 代码块:
    1. 静态代码块:类加载的时候就执行,执行一次。
      1. 什么时候才会类加载?
        1. 使用new方法实例化对象时
        2. 使用Class.forName(“类名”)时
    2. 实例代码块:每创建一个实例执行一次
    3. 代码块的执行都在构造方法之前
      example:
Demo.java:
public class Demo {
    public Demo(){
        System.out.println("构造方法");
    }

    {
        System.out.println("实例代码块");
    }//实例代码块: 创建对象才被调用,每创建一个对象执行一次!


    static{
        System.out.println("静态代码块");
    }// 静态代码块:类加载的时候被调用,只调用一次。
    public void say(){//实例方法:它的执行必须依赖对象
        System.out.println("说话");
    }
    public static void sayStatic(){//静态方法:它的执行不必依赖对象
        System.out.println("说话静态方法");
    }
    public void fn1(){
        System.out.println("实例方法");
        fn2();//实例方法允许调用静态方法
    }
    public static void fn2(){
        System.out.println("静态方法");
        //fn1(); 这样就不ok
        //这样相当于 this.fn1();
        //static 和 this 是水火不容的
        //静态方法不能调用实例方法
    }
}

?

DemoTest.java
public class DemoTest {
    @Test
    public void test1() throws ClassNotFoundException {
        Demo demo1= new Demo();
        Demo demo2= new Demo();
        //先执行静态代码块,再执行实例代码块,再执行构造方法
        Demo demo3;//代码块不执行
        Demo demo4 = null;//代码块不执行
        //在下列情况 才会执行代码块
        new Demo();
        Class.forName("com.yys.Demo");//限定名,全程 有包有类名

        Class c1 = new Demo().getClass();
        System.out.println(c1.getName());//限定名
        System.out.println(c1.getSimpleName());//类名

    }

    public static void main(String[] args) {
        Demo demo = null;
        demo.say();

        Demo.sayStatic();
        demo.sayStatic();//一样的 编译后都是Demo.sayStatic();
    }
}

类的继承,抽象及接口

  1. 继承的目的:为了扩展
    1. 向上抽象
    2. 向下具化
  2. 例子
public class Student extends Person{

    public void read(){
    this.name;
    }
}
//Student是子类,继承了父类Person
  1. 子类中对父类哪些东西是可见的
    protected修饰的方法
    protected修饰的方法或变量在子类中(内部)可以访问。相当于 子类+同包,
    对象与protected无关!
  2. 子类中写的方法可以用@Override进行检测 检测该方法是不是冲写的,父类是不是有这个方法
  3. 方法的重写:
    1. 方法修饰符不能低于原来
    2. 如果父类的方法是void,重写的方法必须是void
    3. 如果父类的方法有返回值,重写的方法不能比父类中原方法的返回类型更抽象()
    4. 抛异常不能比原来更抽象
  4. super作用
    1. 在子类中访问父类对象
    2. 如果不存在方法的重写,this.调用父类的方法
    3. 调用父类构造方法

尽量保留默认的无参数构造 不然的话继承时很麻烦 会报错 因为子类构造方法的参数只能比父类的参数更多


类的继承

1).继承的概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

2).继承格式
通过extends关键字可以实现类与类的继承
class <子类名> extends <父类名> {方法体}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
子类只能继承父类所有非私有的成员(成员方法和成员变量),子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
3).继承的效果
扩展功能
提高代码复用率
让类与类之间产生了关系,是多态的前提
增强了类的耦合性
4).继承的特点
Java只支持单继承,不支持多继承;
Java支持多层继承(继承体系).
5).super关键字
调用父类构造方法
调用父类成员方法
调用父类成员变量
6).使用继承注意事项
子类中所有的构造方法默认都会访问父类中空参数的构造方法。
子类中要使用父类成员变量, 因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。
如果父类没有无参构造方法,子类怎么办?
在父类中添加一个无参的构造方法
子类通过super去显示调用父类其他的带参的构造方法
子类通过this去调用本类的其他构造方法,本类其他构造也必须首先访问了父类构造
子类中的成员变量和父类中的成员变量名称一样时,在子类中访问一个变量的查找顺序是怎样的?
在子类的方法的局部范围找,有就使用
在子类的成员范围找,有就使用
在父类的成员范围找,有就使用
如果还找不到,就报错


方法的重写

1).什么是方法重写?
子类中出现了和父类中一模一样的方法声明(方法名,参数列表,返回值类型),也被称为方法覆盖,方法复写。

2).方法重写(Override)和方法重载(Overload)的区别?
Override是覆盖的意思,也就是重写,它与返回值类型无关,只看参数列表;

Overload是重载的意思,表示在同一个类中,允许存在一个以上的同名函数,只要他们的参数个数或者参数类型不同即可;

两者不同主要体现在:目的不同、范围不同、参数要求不同、返回类型不同。

同:overload用于增加程序的可读性(做法不同,但是做的同一事情)。 override用于提供其超级类已经提供的方法的特定实现。
同:overload 在相同的类范围内内执行。 override发生在两类具有继承(继承)的关系。
参数要求不同:overload参数必须不同。 override参数必须相同。
返回类型不同:overload中可以相同或不同。 override必须是相同的或协变的。
3).方法重写的应用?
当子类需要父类的功能,但是父类功能不满足自身的时候,可以重写父类中的方法。

4).方法重写的注意事项
父类中私有方法不能被重写。因为父类私有方法子类根本就无法继承;
子类重写父类方法时,访问权限不能更低。 最好就一致
子类重写父类方法时,如果父类方法带有异常,则子类异常范围必须一致或更小
子类重写父类方法的时候,最好声明一模一样

final关键字

1).final修饰类被修饰类不能被继承.2).final修饰方法被修饰的方法不能被重写.3).final修饰变量①局部变量——基本类型基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。

public class FinalDemo1 {
public static void main(String[] args) {
        // 声明变量,使用final修饰
        final int a;
        // 第一次赋值
        a = 10;
        // 第二次赋值
        a = 20; // 报错,不可重新赋值
        // 声明变量,直接赋值,使用final修饰
        final int b = 10;
        // 第二次赋值
        b = 20; // 报错,不可重新赋值
    }
}

② 局部变量——引用类型引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改。

public class FinalDemo2 {
    public static void main(String[] args) {
        // 创建 User 对象
        final User u = new User();
        // 创建 另一个 User对象
        u = new User(); // 报错,指向了新的对象,地址值改变。
        // 调用setName方法
        u.setName("张三"); // 可以修改
    }
}

③成员变量成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:显式初始化:

public class User {
    final String USERNAME = "张三";
    private int age;
}

构造方法初始化:

public class User {
        final String USERNAME ;
        private int age;
 
        public User(String username, int age) {
            this.USERNAME = username;
            this.age = age;
    }
}

被final修饰的常量名称,一般都有书写规范,所有字母都大写,且用下划线式。


对象创建过程

  • 创建创建父类对象(父类对象创建也是如此)
  • 加载类对象 : 静态代码块
  • 默认初始化 成员变量
  • 显式初始化成员变量
  • 实例代码块
  • 构造方法

如果想让继承的类构造它的父类的所有参数以及子类独有的参数:

Person.java
public class Person {
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void setName(String name){
        this.name = name;
    }
    public void setAge(){
        this.age = age;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
    public void showMsg(){
        System.out.print("姓名:" + this.getName());
    }
}
Student.java
public class Student extends Person {
    private int score;

    public void setScore(int score) {
        this.score = score;
    }

    public int getScore() {
        return score;
    }
    public Student(){
    }
    public Student(String name,int age,int score){
        super(name,age);
        this.score = score;
    }
    public void exam(){
        System.out.println("考试得了:" + score + "分");
    }
    @Override
    public void showMsg() {
        super.showMsg();
        System.out.print("同学,");
        exam();
    }
}

在写子类的全参数构造方法时要先用super实例化父类。

对象的创建过程

例子:创建一个工具类,一个MyObject对象,一个MyMy对象继承MyObject:

MyUtils.java
    public class MyUtils {    public static int getValue(){        return 99;    }}

MyObject.java
    public class MyObject {
    int a = 10;
    int b = MyUtils.getValue();
    {
        System.out.println("实例代码块: MyObject");
    }
    static{
        System.out.println("静态代码块: MyObject");
    }
    public MyObject(){
        System.out.println("构造方法: MyObject");
    }
}
MyMy.java
    public class MyMy extends MyObject {
    int a = 10;
    int b = MyUtils.getValue();
    {
        System.out.println("实例代码块: MyMy");
    }
    static{
        System.out.println("静态代码块: MyMy");
    }
    public MyMy(){
        System.out.println("构造方法: MyMy");
    }
}
Test.java
    public void test1() {    new MyMy();}

结果:
静态代码块: MyObject
静态代码块: MyMy
实例代码块: MyObject
构造方法: MyObject
实例代码块: MyMy
构造方法: MyMy

即:

  • 创建父类对象(父类对象创建也是如此)
  • 加载类对象 : 静态代码块
  • 默认初始化 成员变量
  • 显式初始化成员变量
  • 实例代码块
  • 构造方法

1. 什么叫做类与类的继承,作用是什么?
    1)多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
    2)作用:
    扩展功能
    提高代码复用率
    让类与类之间产生了关系,是多态的前提
    增强了类的耦合性
2. 继承后,父类与子类之间,各成员有什么样的影响?
调用子类,先进行父类的参数定义和构造器构造,再进行子类的参数定义和构造器构造;
如果子类构造器中没有 super() 语句,或 super() 语句中不含参数;会去寻找父类当中不含参数的构造器;有参数时,寻找有对应参数的父类构造器;
父类中的函数 protected 参数声明,尽量少用,可以通过父类构造函数使用父类中 private 参数;
3. 子类中,如何调用父类的成员?如何使用本类的成员?
    1)直接实例化父类的成员
    2)如果继承了父类的成员函数(指没有新写覆盖),则直接写成员函数名+参数来调用。
         如果没法继承(指的是父类的私有成员函数)则不能调用。
         如果可以继承(父类的保护或公有成员函数),但覆盖了(比如同名重写或虚函数重写)则可用:“ 父类名::成员函数名(参数); ” 来调用。
4. 抽象方法与普通成员方法有什么区别?
5. 抽象类与普通类有什么区别?
何为抽象类?抽象类是从其他若干个具有相同属性与行为的类中进一步抽象出来的类,可以设计方法,属性,如果把类设计为抽象类,那么这个类是不能被实例化的,只能被继承的子类(子类也可以为抽象类,也可以不是)间接使用,抽象类有构造,是一个完整的类。
抽象类不能使用new方法进行实例化,没有具体实例对象。抽象类有点类似“模板”的作用,目的是根据其格式来创建和修改新的类。对象不能由抽象类直接创建,只可以通过抽象类派生出新的子类,再由其子类来创建对象。当一个类被声明为抽象类时,要在这个类前面加上修饰符abstract。
在抽象类中的成员方法可以包括一般方法和抽象方法。抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型、方法名称和所需的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现。当一个方法为抽象方法时,意味着这个方法必须被子类的方法所重写,否则其子类的该方法仍然是abstract的,而这个子类也必须是抽象的,即声明为abstract.

###编码体系

所有编码无条件兼容ascii码
unicode码以\u开头 以一个十六位的数字代替四个二进制数字,unicode可以显示所有语言
utf-8是unicode的一种表现形式

关于Scanner

  1. Scanner中的nextInt方法和nextDouble方法:如果使用nextInt方法,如果输入了double型的参数,会报错,但是反之不会 因为int和double的精度不同,java为了不让数据丢失 不会让double进入nextInt方法
  2. 如果先写了nextline,后写nextInt,可以正常运行,但是先写了nextInt 后写了nextline 就不行了 因为nextline检测的是你的回车符,你写了int值之后敲回车 会默认也进行nextline方法,并将值赋值为空。
    若要避免这种情况,可以将代码修改为:
String ageStr = sc.nextline();
int age = Integar.parseint(ageStr);
String str = sc.next();
sout(str + 1);
  1. 如果输入一串字符 只想得到它的第一个字母:
sc.nextline().charAt(0);