cpu运算是以int进行运算的,所以,数据类型优先以int为主 基本数据类型都有其最大值与最小值. 如果超过其范围,则会发生上溢或者下溢. 因为,在其范围不确定的情况下,应该对其做范围判断(其包装类的静态常量),如果超出范围,则改变数据类型,防止出现问题. 以int为例,如果其最大值+1, 数据会上溢,结果是该值会变为int’的最小值. 小数在程序中默认为是double数据类型. 所以,如果将小数定义为float时,需要在小数后加 ‘f’标识. 基本数据类型与其包装数据类型可以自动转换,也可以通过其包装数据类型的.valueof(包装类)进行转化为基本数据类型 Java高精度数字 BigInteger(整数,超过19位之后使用,不会丢失精度) BigDecimal(小数) java三大要素: 封装 继承 多态
封装:私有成员变量,对外提供公共的访问接口. 继承:基于父类,对功能进行扩展 多态: 前提是 1.继承 2. 重写 3. 父类引用指向子类对象
指向子类的父类引用, 会保存父类的共有的变量方法,以及子类对父类的重写的方法(重写了内部逻辑,,其实也不能说是重写). 只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。 多态机制遵循的原则概括为:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
松耦合. 高内聚 紧封装
耦合: 既是关联关系. 多态可以实现松耦合, 实现类与类或者模块与模块之间的松耦合.既提供一个固定的接口以及参数类, 通过多态, 会实现通过调用更少的接口实现更多的功能. 既接口与实现的分离性. 易于扩展 内聚 : 只是一个类的功能单一明确. 就是一个类处理的事物明确且一致. 不会出现不相干的其他事物. 参考链接: https://www.cnblogs.com/chenssy/p/3372798.html (此处链接,内容讲的very good) 类及成员变量的修饰符
类
访问权限修饰符 a. public: 公共访问类 b. 默认修饰符: 友好类, 只允许同包以及其包下的类访问 非访问权限修饰符 a. abstract: 抽象类, 不能创建实例, 要求被继承并且实现其抽象方法 b. final : 终结类, 不能被继承. 成员变量修饰符
访问权限修饰符 a. public -> 同类修饰符public类似 b protected -> 受保护成员变量. 只能被该类及其子类访问 c. 默认修饰符 -> 只能被同包及其子包下的类访问 d. private -> 再能在该类中访问
非访问权限修饰符 a. static -> 静态成员变量 b. final -> 最终变量,也就是符号常量 c. volatile -> 可供多个线程共同修改的变量 成员方法修饰符
访问权限修饰符 a. public -> 同类修饰符public类似 b protected -> 受保护成员变量. 只能被该类及其子类访问 c. 默认修饰符 -> 只能被同包及其子包下的类访问 d. private -> 再能在该类中访问
非访问权限修饰符 a. abstract 用abstract修饰的方法为抽象方法,抽象方法只有类的声明,没有类的实现。 b. static 用static修饰的方法为静态方法,静态方法属于整个类。 c. final 用final修饰的方法为最终方法,最终方法不能被当前类的子类重新定义。 e. synchronized 用synchronized修饰的方法为同步方法,同步方法主要用于多线程共存的程序中的协调和同步。 算术运算符 逻辑运算符 关系运算符 学习链接: http://blog.csdn.net/typa01_kk/article/details/45000535 Java对象的创建, 类的初始化与实例化 学习链接: http://blog.csdn.net/justloveyou_/article/details/72466416
在准备实例化一个类的对象前,首先准备实例化该类的父类,如果该类的父类还有父类,那么准备实例化该类的父类的父类,依次递归直到递归到Object类。此时,首先实例化Object类,再依次对以下各类进行实例化,直到完成对目标类的实例化。具体而言,在实例化每个类时,都遵循如下顺序:先依次执行实例变量初始化和实例代码块初始化,再执行构造函数初始化。也就是说,编译器会将实例变量初始化和实例代码块初始化相关代码放到类的构造函数中去,并且这些代码会被放在对超类构造函数的调用语句之后,构造函数本身的代码之前。 类的初始化是指类加载过程中的初始化阶段对类变量按照程序猿的意图进行赋值的过程;而类的实例化是指在类完全加载到内存中后创建对象的过程。 类在实例化的过程中,会给其成员变量自动赋值. 类的成员方法中的局部变量以及语句块中的变量, 则不会给其赋值.
向上转型的好处
减少重复代码,使代码变得简洁。
提高系统扩展性。
举个例子:比如我现在有很多种类的动物,要喂它们吃东西。如果不用向上转型,那我需要这样写:
public void eat (Cat c){
c.eat();
}
public void eat (Dog d){
d.eat();
}
eat(new Cat());
eat(new Cat());
eat(new Dog());
一种动物写一个方法,如果我有一万种动物,我就要写一万个方法,写完大概猴年马月都过了好几个了吧。好吧,你很厉害,你耐着性子写完了,以为可以放松一会了,突然又来了一种新的动物,你是不是又要单独为它写一个eat方法?开心了么?
那如果我使用向上转型呢?我只需要这样写:
public void eat (Animal a){
a.eat();
}
eat(new Cat());
eat(new Cat());
eat(new Dog());
恩,搞定了。代码是不是简洁了许多?而且这个时候,如果我又有一种新的动物加进来,我只需要实现它自己的类,让他继承Animal就可以了,而不需要为它单独写一个eat方法。是不是提高了扩展性?
向下转型注意事项
向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)
向下转型只能转型为本类对象(猫是不能变成狗的)。
大概你会说,我特么有病啊,我先向上转型再向下转型??
我们回到上面的问题:喂动物吃饭,吃了饭做点什么呢?不同的动物肯定做不同的事,怎么做呢?
public void eat (Animal a){
if (a instanceof Dog){
Dog d = (Dog)a;
d.eat();
d.run();
}
if (a instanceof Cat){
Cat c = (Cat)a;
c.eat();
System.out.println("我也想跑,但是不会" );
}
a.eat();
}
eat(new Cat());
eat(new Cat());
eat(new Dog());
现在,你懂了么?这就是向下转型的简单应用
public class Demo {
/**
* 目的: 测试类实例化时的执行顺序
*/
private int j;
private int argu;
{
j = 3 ;
argu= getArgu();
System.out.println("代码快执行" );
}
public Demo () {
super ();
System.out.println("开始初始化" );
System.out.println("argu = " +this .argu);
System.out.println("j = " +this .j);
}
static {
System.out.println("执行静态代码块" );
}
public int getArgu () {
System.out.println("实例变量初始化" );
return j;
}
public static void main (String[] args) {
System.out.println("main start" );
Demo demo = new Demo();
System.out.println("main end" );
}
}
执行静态代码块
main start
实例变量初始化
代码快执行
开始初始化
argu = 3
j = 3
main end
public class Demo {
/**
* 目的: 测试类实例化时的执行顺序
*/
private int j;
private int argu= getArgu();
{
j = 3 ;
System.out.println("代码快执行" );
}
public Demo () {
super ();
System.out.println("开始初始化" );
System.out.println("argu = " +this .argu);
System.out.println("j = " +this .j);
}
static {
System.out.println("执行静态代码块" );
}
public int getArgu () {
System.out.println("实例变量初始化" );
return j;
}
public static void main (String[] args) {
System.out.println("main start" );
Demo demo = new Demo();
System.out.println("main end" );
}
}
执行静态代码块
main start
实例变量初始化
代码快执行
开始初始化
argu = 0
j = 3
main end
比较上方两处代码与输出结果可知: 代码块处进行成员变量初始化时,会对成员方法进行编译; 如果在成员变量定义时进行初始化, 则不会对成员方法进行编译, 只会按照jvm规则,给其赋默认值
public class Demo {
/**
* 目的: 测试类实例化时的执行顺序
*/
private static int j;
private static int argu;
{
System.out.println("代码快执行" );
}
public Demo () {
super ();
System.out.println("开始初始化" );
System.out.println("argu = " +this .argu);
System.out.println("j = " +this .j);
}
static {
j = 3 ;
argu = getArgu();
System.out.println("执行静态代码块" );
}
public static int getArgu () {
System.out.println("实例变量初始化" );
return j;
}
public static void main (String[] args) {
System.out.println("main start" );
Demo demo = new Demo();
System.out.println("main end" );
}
}
执行结果
实例变量初始化
执行静态代码块
main start
代码快执行
开始初始化
argu = 3
j = 3
main end
总结 : 初始化执行顺序 : 优先加载静态成员变量以及静态成员方法,然后对其进行初始化 ; 其次初始化类的成员变量以及成员方法. 将其加载至构造方法内. this () 或者super ()之后.
this关键字的作用
调用本类的成员变量 调用本类的其他方法 调用本类的构造方法, 如果在本类的无参构造中调用有参构造实现类的实例化 还可以作为返回值返回该类的实例 super关键字的使用
在实例化子类时,其所有父类均已实例化. 使用super关键字可以访问其上一级父类的成员方法.和成员变量 this与super不能同时出现在子类的构造函数中. 子类在初始化时,. 其构造方法中会默认super();,既先去初始化父类. 复用类
组合语法
其内由其他类组合而成. 扩展性比较好,开发者可以按照需求任意组合 继承 1、子类拥有父类非private的属性和方法。 2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。 3、子类可以用自己的方式实现父类的方法 4.. 父类构造器,只能被子类调用,却不能被继承 5.对于继承而已,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事 继承的缺陷
父类变,子类就必须变。 继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。 继承是一种强耦合关系 是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承 继承与组合的中庸之道 –> 代理
比如拿太空飞船举例, 太空飞船有本身特性,比如 名称, 大小等. 太空飞船还需要一个控制器, 来操控其 前进, 后退等功能. 此时, 如果想要使用太空飞船操控其控制器, 如果使用太空飞船继承控制器, 不符合继承的规则, 如果将该控制器作为该类的成员变量,使用成员方法进行操控,则使该类功能杂乱. 此时 可以使用代理模式, 将飞船的名称等标识以及控制器作为该代理类的成员变量,通过该代理类的成员方法内调用控制器的方法.将代理类的成员方法向外暴露即可. 总结:此模式,既能保证飞船以及控制器的功能单一性, 极好的增强了代码的复用性. 返回值类型:
协变返回类型
协变返回类型指的是子类中的成员函数的返回值类型不必严格等同于父类中被重写的成员函数的返回值类型,而可以是更 “狭窄” 的类型。 参考链接 : https://www.cnblogs.com/sanra/p/4198939.html
返回值类型为基类,返回引用指向子类的父类引用. 其既可以使用多态的特性,容扩展, 又可以将该对象向下转型获取其子类的特有属性和方法进行使用.
重写 1、在子类中可以根据需要对从基类中继承来的方法进行重写。 2、重写的方法和被重写的方法必须具有相同方法名称、参数列表和返回类型。 3、重写方法不能使用比被重写的方法更严格的访问权限。 此概念并未到重载方法.是java对返回值规则的约定
方法重载的要求就是两同一不同:同一类中方法名相同,参数列表不同。 至于方法的其他部分,如方法返回值类型、修饰符等,与方法重载没有任何关系。