java基本数据类型
- 基本数据类型主要有:char、byte、short、int 、long、float、double、bool ean。
- int 所占空间:4字节, 存储大小:-2^31 ~ 2^31-1.
- byte 所占空间: 1字节, 存储大小: -2^7 ~ 2^7-1.
- short 所占空间: 2字节, 存储大小: -215~215-1.
- long 所占空间: 8字节, 存储大小: -263~263-1.
- char 所占空间: 2字节(一个中文字符占两个字节)可存储(‘1’)(‘你’),
- float 所占空间: 4字节, 存储大小: -3.403e38~3.403e38.
- double 所占空间: 8字节, 存储大小: -1.798e308~1.798e308.
- boolean 所占空间: 1字节,只有true和false, 默认为false
- int的使用
int i = 1,
i++ 等于 i+ = 1, 对i加一再取值。
++i : 先取i的值再对i进行+1. - 类型转换
当short s1 = 1, s1 = s1 + 1会报错, 类型向下转换需要强制转换。
当使用 s1++时; 不会报错, 因为s1++隐含了强制转换,s1++ 等于 s1 = (short)(s1+1); - byte 和 String 以及long是否可作为 switch(expr)里面的expr参数。
在java5以前, expr只支持byte, char, int的基本类型。 java5以后, expr支持枚举emun。 在java7以后 expr支持String 类型。 long类型一直到现在都不能做为expr来做switch的条件。
装箱和拆箱
- 装箱:基本数据类型自动转换为包装器类型的过程
- 拆箱:包装器类型自动转换为基本数据类型的过程
public class IntegeTest {
public static void main(String[] args) {
int total = 1;
Integer ta = total;
// 自动装箱的过程(实现原理: Integer integer = Integer.valueOf(total);)
System.out.println(ta);
Integer num = 26;
int n = num;
// 自动拆箱的过程(实现原理: Integer tatal = new Integer(1);)
System.out.println(ta);
}
}
面对对象
- 抽象: 我们把一类对象的共同特征构造出来,把他们的共同行为和属性抽象为一个对象的过程。抽象只关注他们的行为和属性, 并不知他们的行为具体是什么。
面对对象的三大特征
封装、继承、多态。
- 封装
我们把对象的共同特征抽取出来为一个对象, 该对象不实现方法, 而是由实现或者继承他的子类来实现, 当我们需要获取结果时, 通过父类引用去指向子类实例对象获取结果。 让类对外只暴露接口, 对内封装类的实现。 - 继承
java类只支持单继承,但接口可多继承。所谓继承是子类继承父类,子类可调用父类没有private修饰的所有方法和属性。 并且可通过super()来调用父类构造器。 子类还可重写父类方法。在父类的基础上扩展自己的属性和方法。 - 多态
多态分为运行时多态和编译时多态,实现多态需要类继续父类并重写父类方法,或者实现接口。在程序未运行时,并未可知调用的是哪个方法。 在程序运行时, 需要父类引用去指向子类实例化的对象,父类引用可以指向子类重写的父类方法。并且可以调用父类方法。这种指向在程序未运行时未可知。
Math.round(11.5)和Math.round(-11.5) - java的round取整是 浮点型加上 0.5然后去掉余数。 所以 Math.round(11.5) = 12 , Math.round(-11.5) = -11。
long = 11, 和 float = 11.5是否正确 - 编译器会报错, 正确应该写为 long = 11L,float = 11.5F。
面对对象的五大原则 - 单一职责原则
类的功能要单一, 不能包罗万象, 什么功能都有。就例如通话是一个类,视频是一个类,短信是一个类。不能一个类通话、视频、短信都属于一个类。 - 里氏替换原则
子类可以替换父类出现在的任何地方。 - 依赖倒置原则
高层次的类不能依赖于低层次的类 - 开放封闭原则
java类对于向外扩展开放, 对内修改封闭。 就是说在我的功能上扩散是可以随便扩展,但是想修改我里面类的功能是绝对不允许的。 - 接口分离原则
接口的设计是根据特定的功能或需求
内部类 - 成员内部类
成员内部类可以访问类里面的所有属性, 但不可改变属性的值, 可以把属性的值赋予类的内部属性再去改变它。
class Test {
private int b =2;
private static int c = 1;
public void test1(){
int a = 1;
class Demo2{
public void test(){
// a = a+ 1;
int d = a + 1;
System.out.println("这是成员内部类: "+ d +"+"+ c);
}
}
Demo2 demo2 = new Demo2();
demo2.test();
}
public static void main(String[] args) {
Test test = new Test();
test.test1();
}
}
- 局部内部类
定义在方法内部的类, 可以访问成员变量和局部变量。访问的局部变量需要加上fa
public class test {
public void test1(){
Object o = new Object(){
public void test(){
System.out.println("1111");
}
};
}
}
- 静态内部类
静态内部类可以访问类内的所有静态属性。
class Test {
private int b =2;
private static int c = 1;
public static class Demo2{
// private int b;
public void test(){
// int a = b;
int d = c;
c = c + 1;
System.out.println("这是成员内部类: "+ d +"+"+ c);
}
}
// public void test1(){
//
// }
public static void main(String[] args) {
new Test.Demo2().test();
}
}
- 匿名内部类
匿名内部类为在方法内部实现接口, 实现接口的方法, 隐藏内部实现。 有很好的封装性。
class Test {
private int b =2;
private static int c = 1;
public void test1(){
int a = 1;
new Demo2 () {
public void test(){
System.out.println("静态内部类!");
}
}.test();
}
public static void main(String[] args) {
Test test = new Test();
test.test1();
}
}
interface Demo2{
void test();
}
反射
- 获取反射的三种方法
- 通过对象引用的 .getClass方法获取
- 通过类名.class方法获取
- 通过类名包路径来获取
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
// 方法一 通过对象引用的 .getClass方法获取
Demo1 demo1 = new Demo1();
Class<? extends Demo1> aClass = demo1.getClass();
System.out.println("aClass类的名称为" + aClass.getName());
// 方法二 通过类名.class方法获取
Class<Demo1> demo1Class = Demo1.class;
System.out.println("demo1Class类的名称为" + demo1Class.getName());
// 方法二 通过类名包路径来获取
Class<?> aClass1 = Class.forName("Demo1");
System.out.println("demo1Class类的名称为" + aClass1.getName());
}
}
class Demo1 {
public void test(){
System.out.println("1111");
}
}
反射在我们的正常开发中并不常用,但是反射是java框架的核心, 理解反射对理解框架底层非常有用。
java方法参数
java的参数传递都是值传递。
- 对于基本类型的值传递, java会把把基本类型的参数复制一遍, 只会对复制的值做动作。
- 对于引用作为参数类型,
hashCode()和equals()
hashCode() 属于Object的方法, 用其他编程语言编写的方法。
重写hashCode(), 把当前对象引用地址转换为整数型的值。用来判断两个对象引用是否相等。
- 重写hashcode时,可以调用Arrays的hash方法来获取hash值。 内部实现了上一个属性乘以31 加上当前属性的hash值叠加来获取最后的hash值。以此来保证hash值的随机性。
- 重写equals时, 需要对比自反性,是否同一个类。 最后在比较类的内容是否一样。 所有一般都是先比较hash值,再去比较equals, 来降低equals比较类的内容是的性能。
public class user {
private Integer id;
private String name;
private String password;
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
@Override
public int hashCode(){
Objects.hash(getId(),getName(), getPassword());
//Objects.hash调用的是Arrays.hashCode的hasjCode方法, 里面的实现类似下面这样
// int result = (id != null) ? id.hashCode() : 0;
// result = 31 * result + ((name != null) ? name.hashCode() : 0);
// result = 31 * result + ((password != null) ? password.hashCode() : 0);
//
// return result;
}
@Override
public boolean equals(Object o){
// 自反性
if(this == o){
return true;
}
// 比较是否为同一类型
if (!(o instanceof user)){
return false;
}
// 类型强制转换
user user = (user) o;
// 比较属性是否相等
return getId() == user.getId() && getName() == user.getName() && getPassword() == user.getPassword();
}
}
字符串
字符串类型和字符类型的区别:
- 字符类型只存储一个字符,字符串存储多个字符,字符串的底层实现是一个字符数组组成的。
- 字符串是final修饰的类。属于不可继承和不可改变的类,所以属于安全的类。
String
字符串是一串连续的字符对象。
- 被final修饰,属于不可继承和不可改变的类,属于线程安全的对象。
- 内部重写hashCode()和equals(), 所以可以作为集合的key。
字符串的创建
public class StringTest {
public static void main(String[] args) {
String s1 = new String("123");
String s2 = new String("123");
// 比较的对象的内容是否相等: true
System.out.println(s1.equals(s2));
// 比较的是对象的引用是否相等: false
System.out.println(s1==s2);
String p1 = "123";
String p2 = "123";
// 比较的是两个的内容是否相等: true
System.out.println(s1.equals(p1));
// 应该new 一个String对象时在堆内存创建一个对象和在字符串常量池保存一份字符串, p1没创建对象时先去字符串常量池获取该字符串。
System.out.println(s1 == p1);
System.out.println(p1.equals(p2));
System.out.println(p1==p2);
}
}
输出:
true
false
true
true
true