0-35,java development kit/java runtime environment/jvm;
javac编译,Java运行。
源文件xxx.java编译多个xxx.class字节码可以被jvm识别。
0-36,如何让JAVA命令运行,把命令写进环境变量让找path。
path作用:为Windows找命令指路。 classpath是为类加载器指路的。
环境变量:分为用户和系统环境变量,
0-51,public class 和class的区别:
public类只能有一个,public可以有或无,若有,其修饰类名必须和源文件名一致。
0-57,标识符由数字,字母,下划线,$组成。
不能数字开头,不能含有空格,不能是关键字,区分大小写。
命名规范:“驼峰命名”,类名,接口名首字母大写;变量,方法名首字母小写;常量全部大写。
在java语言中,如:10,1.23,ture,false,‘a’,"abc"这些数据在程序中都被称作”字面量“。
作用域,出了大括号就不认识了。
0-102,不同类型,jvm分配不同大小空间。
如果int转byte的过程中,int的值在byte范围内,可以直接赋值。
java中整型默认是int,所以long a=2147483648;会报错。解决:long a=2147483648L;
byte是1个字节即8位,1000 0000到0111 1111,因为0代表正号,1代表负号,所以是-128~127.
大类型转小类型,如long 100L转int,会自动砍掉前面的4个字节。
byte,char,short运算会统一变成int; 多种类型运算,最终结果取最大容量类型。
public class IntTest01{
public static void main(String[] args){
long a=10L;
char c='a';
short s=100;
int i=30;
System.out.println(a+c+s+i);
//编译器不知道这个加法最后的结果是多少,只知道是long类型。
int x=a+c+s+i;//错误: 不兼容的类型: 从long转换到int可能会有损失
int x=237; //直接写值是对的。
}
}
java中:任意一个浮点型都比整数型空间大,尽管float是4字节,long是8字节,但是float容量>long容量。
任意一个浮点型数据默认被当作double类型处理
public class FloatTest01{
public static void main(String[] args){
float a=3.14;//错误: 不兼容的类型: 从double转换到float可能会有损失
}
}
改善措施:
一、float a=3.14F;
二、float a=(float)3.14;
单引号字符,双引号字符串;char字符‘’,字符串“”;。
\t是tab键,\n是换行符,\是转义符,
如char x =‘4e2d’; 错误。
char x = ‘\u4e2d’; 正确。\u代表后面一个字符是unicode编码。
计算机底层存储二进制补码,效率高。
正数原码,反码,补码一致。负数符号位不变,反码取反,再加一是补码。
0-103,基本数据类型转换规则:
一、八种基本数据类型,除boolean类型不能转换,其他7种类型都可以转换。
二、如果整数型字面量没有超出byte,short,char的取值范围,可以直接将其赋值给byte,short,char类型的变量。
三、小容量向大容量转换称为自动类型转换,容量从小到大的顺序为:byte<short(char)<int<long<float<double;其中short和char都占用两个字节,但是char可以表示更大整数。
四、大容量转换为小容量称为强制类型转换,编写时必须添加“强制类型转换符”,但运行时可能出现精度损失。
五、byte,short,char类型混合运算时,先各自转换成int类型在运算。
六、多种数据类型混合运算,各自先转化成容量最大的在运算。
**0-108,&&短路与,左边为false则右边就不执行。
0-109,使用扩展赋值运算符的时候,永远都不会改变运算结果类型。**
byte i=100;
i+= 200;
则i诞生以来都是byte类型,i+=200等同于i=(byte)(i+200);
0-198,输出大于某个正整数n的最小质数.
public class Prime{
public static void main(String[] args){
//思路:这个正整数n++,判断是否为质数
printPrime(13);
}
public static void printPrime(int i){
//如果i不是质数,则i继续加 }
while(!isPrime(++i)){
}
System.out.println("大于正整数的最小质数是:"+i);
}
public static boolean isPrime(int i){
for(int x=2;x<i;x++){
if(i%x==0){
return false;
}
}
return true;
}
}
0-136,求和1~100内奇数:
思想:一、1~100内所有的质数,二、求和。
public class Zhishu{
public static void main(String[] args){
int sum=0;
for(int i=1;i<100;i+=2){
sum+=i;
}
System.out.println("1~100质数的和是:"+sum);
}
0-144,break干switch和最近的循环,return干最近的方法.
public class BreakTest{
public static void main(String[] args){
//for循环的嵌套,把内层for循环看成普通的代码。
for(int k=0;k<2;k++){ //外层for
for(int i=0;i<10;i++){ //内层for
if(i==5){
//break干掉的不是if,而是离他最近的循环,内层for。
break;
}
System.out.println("break打断后输出:"+i);
}
}
}
}
0-182,a方法调用b方法时,a和b在同一个类下,'类名.'可以省略.
public class ClassNameTest{
public static void main(String[] args){
print1();
B.print2();
}
public static void print1(){
System.out.println("2020-09-21");
}
}
class B{
public static void print2(){
System.out.println("不在同一个类下,方法调用时类名不能省略!");
}
}
0-191,方法执行时内存变化
方法调用时压栈,分配空间;方法执行结束后弹栈,释放空间.
0-283,关于System.out.println().
public class SystemTest{
//静态变量
static Out out = new Out();
public static void main(String[] args) {
//这个SystemTest是一个类名,调静态变量out,然后调方法.
SystemTest.out.println();
}
}
class Out{
//实例方法
public void println(){
System.out.println("地狱训练!");
}
}
0-207,递归是方法自己调用自己,必须有结束条件,否则会栈溢出。
public class Recursion{
public static void main(String[] args){
System.out.println(recursion(4));
}
//第一要素:明确你这个函数想要干什么:计算1~n的和
public static int recursion(int n){
//第二要素:寻找递归结束条件
if(n==1){
return 1;
}
//第三要素:找出函数的等价关系式
return n*(n-1);
}
0-230,Java执行的内存图
package com.东京热.javase.ram;
//首先加载类,然后调方法入栈,引用指向堆对象。
public class Ram_2 {
public static void main(String[] args) {
//方法传参即把把变量中保存得值复制一份,传过去.
Address a = new Address("日本","东京热","121121");
User u = new User(11111,"张三",a);
System.out.println(u.username+a.city);
}
}
class Address{
String city;
String stree;
String zipcode;
public Address(String city, String stree, String zipcode) {
this.city = city;
this.stree = stree;
this.zipcode = zipcode;
}
}
class User{
int id;
String username;
Address addr;
//构造方法作用:创建对象并初始化成员变量.
//对于实例变量,只要没有手动给构造方法赋值,系统都会默认赋值.赋值发生在构造方法被调用时.
public User() {
}
public User(int id, String username, Address addr) {
this.id = id;
this.username = username;
this.addr = addr;
}
}
0-239,一个类没有构造方法,系统会自动指定无参构造方法,作用就是初始化成员变量。
调构造方法:new 类名(同构造方法名)
如果手动提供有参构造方法,则系统不提供无参构造方法.
0-250,封装作用:化繁为简,为了安全.
步骤:属性私有化,set写值,get读值.
0-252,只要是方法:静态方法,实例方法,构造方法运行时都会压栈,只不过构造方法弹栈时会在堆区创建对象.
0-253,局部变量引用在栈中;对象,以及对象的实例变量在堆里,静态变量在方法区.
运行时,jvm把
Demo01PhoneOne的信息都放入方法区,当引用访问静态时会自动转变为"类.访问".
1、敲完java Demo01PhoneOne后,启动JVM和classloader,从classpath中找到.class字节码文件,装进jvm,启动解释器把其转变为二进制并读取,然后把该类的类信息存放到方法区,
这一过程称为类加载
2、执行main()方法;Phone one = new Phone();JVM在方法区加载Phone类的类型信息并在堆中为Phone实例分配内存,其中引用指向方法区Phone类的类型信息;
3、执行方法:one.call();JVM根据栈中引用,定位堆中Phone实例,再根据Phone实例持有引用,定位方法区中Phone类的类型信息,从而获得call()方法的字节码,执行方法中指令。
0-255,什么时候用静态方法?什么时候用实例方法?
public class ExampleMethod{
public static void main(String[] args){
User u = new User();
u.setId(10);
System.out.println(u.getId());
}
}
//当这个方法体当中,直接访问了实例变量,这个方法一定是实例方法.
class User{
//id在这里是实例变量
private int id;
public void setId(int id){
this.id=id;
}
public int getId(){
//访问的id是实例变量,所以getId()必须是实例方法.
return id;
}
}
什么时候用静态变量?什么时候用实例变量?
public class Chinese{
//id随对象变而变.
int id;
//国籍不随对象变而变,属于整个类的特征.
static String country;
}
0-258,静态代码块作用记录类加载日志信息。
public class StaticTest{
static{ //一个类中可以编写多个静态代码块。
System.out.println("A");
System.out.println("B");
}
public static void main(String[] args){
System.out.println("D");
}
//静态代码块类加载时只执行一次,并且早于main方法之前。
static{
System.out.println("C");
}
}
0-260,实例语句块作用提取多个构造方法中的共同代码。
public class InstanceTest{
public static void main(String[] args){
System.out.println("A");
new InstanceTest();
}
//只要构造方法执行,实例语句块必执行,并在构造方法之前main之后执行。
{
System.out.println("实例语句块执行了!");
}
public InstanceTest(){
System.out.println("无参的构造方法执行了!");
}
}
0-259,静态代码块和静态变量在类加载时执行,在方法区开辟空间存储;实例变量在new对象时在堆区开辟空间。
public class StaticTest01{
int i=10;
static{
//静态代码块中i变量无法取得实例变量i的值。
i=i+1;
}
}
0-263,静态方法中不能出现this。
语法角度:当这个方法体当中,直接访问了实例变量,这个方法一定是实例方法.
思想角度:this代表当前对象,而静态方法就不存在对象.
public class Student{
private String name;
public static void main(String[] args){
//name是实例变量,必须先new对象,通过“引用.访问”;而这里只能是“this.访问”,然而this代表当前对象。
//而main方法是静态方法就没有对象,所以下面代码不对.
System.out.println(name);
}
}
0-263,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指的类型是什么?该指针指向了哪里?(重点注意)
0-271,在实例方法或者构造方法中,为了区分局部变量和实例变量,this不能省略.
public class ThisTest01{
public static void main(String[] args){
A a = new A();
a.setName("张三");
System.out.println(a.getName());
}
}
class A{
private String name;
public void setName(String name){
//就近原则
//两个name都是局部变量,局部变量值就近原则和参数值一致,和实例变量无关.
//name = name;
//this不能省略,在这里区分局部变量和实例变量.
this.name = name;
}
public String getName(){
//这个this可以省略是因为参数没name,不会产生就近原则.
return name;
}
public A(String name){
this.name=name;
}
}
0-313,如果父类和子类当中有同名属性或者方法,并且希望在子类中访问父类的属性或者方法,则super不能省略.
public class PolymorphicTest4 {
public static void main(String[] args) {
new Son1("子类").shopping();
}
}
class Father1{
String name;
public Father1() {
this.name = "父类";
}
public void shopping(){
System.out.println("父类的方法!");
}
}
class Son1 extends Father1{
//子类也有一个同名属性
private String name;
public Son1(String name) {
this.name = name;
}
public void shopping(){
//在子类中访问父类的属性或者方法
System.out.println(super.name+"在购物!");
System.out.println(this.name+"在购物!");
super.shopping();
}
}
0-272,通过当前构造方法调用本类的构造方法,this(实际参数列表).
public class ThisTest02 {
public static void main(String[] args) {
DateTest d1 = new DateTest();
d1.printDate();
}
}
class DateTest{
private int year;
private int month;
private int day;
public DateTest(){
//通过当前构造方法调用本类的构造方法,必须同一个类.
//只能出现在构造器第一行,作用是代码复用.
this(1949,10,1);
}
public DateTest(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void printDate(){
System.out.println("构造方法:"+this.year+"年"+this.month+"月"+this.day+"日");
}
}
0-263,谁调用实例方法谁就是this,this代表当前对象则this可以省略。
public class ThisTest{
public static void main(String[] args){
A a = new A();
a.shopping("张三");
//一个对象一个this,this存储当前对象的引用,并且this存储在堆内存的当前对象内指向自己。
A b = new A();
b.shopping("李四");
}
}
class A {
private String name ;
public void shopping(String name){
//a调用shopping,this是a
//b调用shopping,this是b
System.out.println(name+"在购物!");
}
}
0-277,在程序执行之前,凡是需要加载的类会全部加载到jvm中,然后才会执行main方法.
为什么同一个类下调用方法时"引用"或者"类名"可以省略?
java程序会自动检测带不带static,带自动添加"类名.",不带自动添加"this.".
0-280,父类除了构造方法其他都可以被子类继承,父类的私有属性,子类可以通过封装访问.
object类是所有类的老祖宗,凡是可以采用"is a"描述的都可以采用继承extends.
0-284,分析Object源码中
System.out.println(引用)时会自动调用Object类的toSting方法,打印出"类名@内存地址经过哈希算法得出的十六进制数".
public class Object {
//一个方法不带大括号以";"结尾,并且修饰符中有native关键字,则表示底层调用c++写的dll程序(dll是动态链接库文件).
private static native void registerNatives();
//静态代码块作用记录类加载日志信息。静态代码块类加载时只执行一次,并且早于main方法之前。
static {
registerNatives();
}
//无参的构造方法
@HotSpotIntrinsicCandidate
public Object() {}
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
@HotSpotIntrinsicCandidate
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
@HotSpotIntrinsicCandidate
public final native void notify();
@HotSpotIntrinsicCandidate
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0L);
}
public final native void wait(long timeoutMillis) throws InterruptedException;
public final void wait(long timeoutMillis, int nanos) throws InterruptedException {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
nanosecond timeout value out of range);
}
if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) {
timeoutMillis++;
}
wait(timeoutMillis);
}
@Deprecated(since="9")
protected void finalize() throws Throwable { }
}
0-286,方法的重写: .
两个类必须继承关系,方法的名字,参数,返回值一致;重写之后的方法权限更加开放,抛出的错误更加少
public class OverwriteTest {
public static void main(String[] args) {
Cat cat = new Cat();
cat.move();
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
//子类继承父类的方法无法满足业务需要的场合,考虑方法的覆盖.
class Cat extends Animal{
//方法的重写最好把父类的方法copy过来改动.
public void move(){
System.out.println("青云直上九万里!");
}
}
0-199,方法的重载:同一个类下,方法名相同,参数不同。
用于功能相似的场合。
public class OverloadTest{ public static void main(String[] args){
System.out.println(sum(10,20));
System.out.println(sum(1.1,2.2));
}
public static int sum(int i,int j){
return i+j;
}
public static double sum(double i,double j){
return i+j;
}
}
0-290,因为从Object继承过来的toString方法无法满足子类需求,所以一般在子类重写toString方法.
public class TostringTest01 {
public static void main(String[] args) {
Date data = new Date(1949,10,1);
//我对结果Date@30f39991不满意,希望输出1949-10-01.所以子类重写toString方法.
System.out.println(data);
}
}
class Date{
private int year;
private int month;
private int day;
@Override
public String toString() {
return year + "-" + month + "-" + day ;
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
0-284,Object中含有toString方法:
public class TostringTest{
public static void main(String[] args) {
TostringTest t1 = new TostringTest();
System.out.println("Object中含有toString方法:"+t1.toString());
System.out.println("如果直接输出引用,会默认调用Object的toString方法:"+t1);
}
}
0-300,多态面向抽象编程,如传参是宠物类型而不是具体的猫狗类型,降低耦合度.
public class PolymorphicTest1 {
public static void main(String[] args) {
Master master = new Master();
master.feed(new Dog());
}
}
class Master{
public void feed(Pet pet){
pet.eat();
}
}
class Pet{
public void eat(){
}
}
class Dog extends Pet{
public void eat(){
System.out.println("狗吃骨头!");
}
}
class Fish extends Pet{
public void eat(){
System.out.println("鱼吃蚯蚓!");
}
}
0-287,方法的覆盖只针对方法和属性无关;私有方法不能覆盖;
方法覆盖只针对实例方法,静态方法没有意义.
覆盖的前提是继承,构造方法不能继承,覆盖更无从谈起.
0-292,无论是向上转型(子到父)还是向下转型(父到子)两者必须有继承关系.
自动类型转换和强制类型转换发生在基本数据类型,向上和向下类型转换发生在引用数据类型.
多态即编译阶段一种形态,运行阶段一种形态.
编译阶段绑定父类的方法,运行阶段绑定子类的方法.父类的引用指向子类的对象.
public class OverwriteTest {
public static void main(String[] args) {
Animal animal = new Cat();
//对于"animal.move()"的分析:
//编译阶段,编译器知道animal的类型是Animal,会去Animal.class中找move方法,找到则静态绑定move方法.
//运行阶段,实际堆内存对象是Cat对象,运行阶段会动态绑定Cat的move方法
animal.move();
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void move(){
System.out.println("青云直上九万里!");
}
}
0-294,调用子类特有的方法时需要向下转型.
public class OverwriteTest {
public static void main(String[] args) {
Animal animal = new Cat();
//调用子类特有的方法时需要向下转型.
Cat cat = (Cat)animal;
animal.catchMouth();
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void move(){
System.out.println("动物在移动!");
}
public void catchMouth(){
System.out.println("子类特有的方法!");
}
}
0-295,instanceof判断运行阶段引用指向的类型.
public class OverwriteTest {
public static void main(String[] args) {
Animal animal = new Bird();
编译阶段animal是Animal类型,而Animal和Cat存在继承关系,可以向下转型.编译正常.
//运行阶段由于堆内存实际是Bird对象,而Bird和Cat没有继承关系,所以运行时异常.
Cat cat = (Cat)animal;
cat.catchMouth();
}
}
class Animal{
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal{
public void catchMouth(){
System.out.println("猫在抓老鼠!");
}
}
class Bird extends Animal{
public void move(){
System.out.println("鸟儿在飞翔!");
}
}
0-297,为什么要instanceof判断.
public class Polymorphic {
public static void main(String[] args) {
C c = new C();
c.move(new Bird());
}
}
class C {
public void move(Animal c){
//表示c引用指向,堆内存的对象类型是Bird.
if(c instanceof Bird){
Bird bird = (Bird)animal;
bird.move();
}
}
}
0-304,静态方法覆盖没有意义。
public class PolymorphicTest2 {
public static void main(String[] args) {
Animal1 animal = new Cat1();
//静态方法虽然使用“引用.调用”,实际运行阶段还是“Animal.调用”
animal.move1();
}
}
class Animal1{
public static void move1(){
}
}
class Cat1 extends Animal1{
public static void move1(){
System.out.println("猫在走猫步!");
}
}
0-304,私有方法不能覆盖。
public class PolymorphicTest3 {
private void move(){
System.out.println("私有方法不能覆盖!");
}
public static void main(String[] args) {
PolymorphicTest3 polymorphicTest3 = new AA();
polymorphicTest3.move();
}
}
class AA extends PolymorphicTest3{
public void move(){
System.out.println("重写之后的方法权限更加开放,抛出的错误更加少.");
}
}
0-306,对比this和super:
this只能出现在实例方法和构造方法中; super只能出现在实例方法和构造方法中。 this只能出现在构造方法第一行,通过当前构造方法调用本类的其他构造方法。
this的语法是“this.”,“this()”; super的语法是“super.”,“super()”. super只能出现在构造方法第一行,通过当前构造方法调用"父类"的其他构造方法。
this不能使用在静态方法中。 super不能使用在静态方法中。 super和this在构造方法中,不能共存,因为都必须出现在第一行!
this在区分局部变量和实例变量时不能省略。
public class SuperTest1 {
public static void main(String[] args) {
new Son();
}
}
class Father{
public Father(){
System.out.println("无论何时,子类构造方法执行时必然调用父类构造方法。");
}
}
class Son extends Father{
public Son(){
//super();当一个构造方法第一行既没有this()有没有super(),则默认会有super()
System.out.println("表示子类的构造方法默认调用父类的无参构造方法,必须保证父类的无参构造方法存在!");
}
}
0-310,super的内存图,在构造方法执行过程中,一连串调用了父类的构造方法,但实际上对象只创建了一个。
0-311,super(实参)作用初始化当前对象的父类型特征,并不是创建新的对象。
package com.苍井空.javase.ram;
public class SuperTest03 {
public static void main(String[] args) {
CreditAccount ca1 = new CreditAccount();
CreditAccount ca2 = new CreditAccount("11111",10000,0.999);
}
}
class Account{
private String actno;
private double balance;
public Account() {
}
public Account(String actno, double balance) {
this.actno = actno;
this.balance = balance;
}
}
class CreditAccount extends Account{
private double credit;
public CreditAccount() {
}
public CreditAccount(String actno, double balance, double credit) {
super(actno, balance);//super是this指向的那个对象中的一块空间
this.credit = credit;
}
}
0-314,super使用时后面必需有一个点。
public class SuperTest2 {
public static void main(String[] args) {
new SuperTest2().m1();
//super不是引用,也不保存内存地址,也不指向任何对象.
//只代表当前对象内部的那一块父类型特征.
new SuperTest2().m2();
}
public void m1(){
System.out.println(this);
}
public void m2(){
//编译错误,需要“.”
System.out.println(super);
}
}
0-316,"super.属性"访问父类的属性,"super.方法"访问父类的方法,"super(参数)"访问父类构造方法.