黑马程序员 ---- java基础加强(上)

时间:2021-12-28 00:42:53
 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————
IDE(Integrated-Development-Environment)集成开发环境


jms即Java消息服务(Java Message Service)


JMX(Java Management Extensions,即Java管理扩展)


JNDI(Java Naming and Directory Interface,Java命名和目录接口)


Java分为三个体系
JavaSE(J2SE)(Java2 Platform Standard Edition,java平台标准版)
JavaEE(J2EE)(Java 2 Platform,Enterprise Edition,java平台企业版)
JavaME(J2ME)(Java 2 Platform Micro Edition,java平台微型版)。


Eclipse和MyEclipse的区别: Myeclipse是插件


工具的作用: 工程化的管理项目


Wrokspace工作台                        Project项目


程序开发分:编译时,运行时


Eclipse配置编译版本,运行版本


配置快捷键   alt+/ 快速不全


一个工作间包含多个工程,一个工作间设置影响下面所有的工程


Perspective  透视图
interview  接见,面试
refactor  重构
view  视图
apply应用
content Assist  内容助理
general  常规
generic 泛型




透视图是多个视图的集合


调试程序:设置断点--debug--选择变量鼠标右键--watch观察变量


设置工作间的javac/java
设置工程的javac/java
javac与java版本一致即可


工作台与工程的关系式:继承与覆盖


配置java模板: try-finally  Editor-Templates
配置模板是:cursor是光标  select-line是选择内容


pattern 模式


java导入工程, Import


Build Path 配置path环境变量
增加Library--多个jar的集合


exteranl 扩展


静态导入:
Import static 语句导入一个类中的某个静态方法或所有的静态方法

package day1;
//静态导入 Math数学工具类
import static java.lang.Math.max;
import static java.lang.Math.abs;
public class StaticImport
{
public static void main(String[] args)
{
//未使用之前
System.out.println(Math.max(10, 12));
System.out.println(Math.abs(-10));

//使用了静态导入 简化书写
System.out.println(max(10, 12));
System.out.println(abs(-10));
}
}




可变参数:
1.只能出现在参数列表的后面
2.  ... 位于变量类型和变量名之间,前后有无空格都可以
3.调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数


package day1;
//可变参数
public class VariableParameter
{
public static void main(String[] args)
{
show("可变参数",1852,1522,122,13,312,01);
}
//注意可变参数不能放在参数列表前面
private static void show(String string,int... arr)
{
System.out.println(string);
for (int i = 0; i < arr.length; i++)
{
System.out.println(arr[i]);
}
}
}



Override 和Overload的区别:
override是复写(覆盖) 权限要大于父类,参数,方法名,返回值要一致
overload是重载,依据是参数列表个数,类型,方法名要一致,与返回值无关


VariableParameter可变参数


增强for循环
语法 for(type 变量名:  集合变量名){...}


package day1;

import java.util.HashMap;
import java.util.Map;


//增强for循环
public class EnhanceFor
{
public static void main(String[] args)
{
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");

for (Map.Entry<String, String> mEntry : map.entrySet())
{
System.out.println(mEntry.getKey()+"---"+mEntry.getValue());
}
}
}



statement 语句


Expression 表达式


自动装箱与拆箱  

package day1;
//自动装箱 拆箱
public class AutoBox
{
public static void main(String[] args)
{
Integer t1=10; //自动装箱
System.out.println(t1+23); //自动拆箱


//小知识点 JDK1.5新特性
//当数值在byte范围之间,就不会在内存新开辟空间.直接从常量池中取出,所以在byte范围他们的引用地址是一样的
Integer i1=100;
Integer i2=100;
System.out.println(i1 == i2 );//true

Integer i3=128;
Integer i4=128;
System.out.println(i3 == i4 );//false

Integer i5=Integer.valueOf(10);//转为基本数据类型
Integer i6=Integer.valueOf(10);
System.out.println(i5 == i6 );//true

}
}



JDK1.5新特性数值在byte范围之间会保存在常量池里面,使用的时候取的是同一个地址


享元设计模式;
很多很小的对象,他们有很多的相同的东西,把他们变成一个对象,还有些不同的东西,把他们作为外部属性用于方法传参


枚举:
枚举只能有固定的值,每一个枚举元素都是对象


ctrl+shift+/ 多行注释


普通类模拟枚举

package day1;
//普通类模拟enum枚举
public class EnumTest1
{
public static void main(String[] args)
{
Lamp_1 lamp_1=Lamp_1.RED;
System.out.println(lamp_1.nextLamp());
System.out.println(lamp_1);
}
//普通类模拟enum
public static class Lamp_1
{
private Lamp_1(){};
public static final Lamp_1 RED = new Lamp_1();
public static final Lamp_1 YELLOW = new Lamp_1();
public static final Lamp_1 GREEN = new Lamp_1();
public Lamp_1 nextLamp()
{
if(this==RED)
{
return GREEN;
}else if(this==GREEN)
{
return YELLOW;
}else
{
return RED;
}
}
@Override
public String toString()
{
return this==RED?"RED":this==YELLOW?"YELLOW":"GREEN";
}
}
}



带抽象方法的普通类模拟枚举


package day1;

//带抽象方法与带构造方法的普通类模拟枚举类
public class EnumTest2
{
public static void main(String[] args)
{
Lamp_2 lamp_2=Lamp_2.RED;
System.out.println(lamp_2.nextLamp());
System.out.println(lamp_2);
}
@SuppressWarnings("unused")
public static abstract class Lamp_2
{
public static final Lamp_2 RED = new Lamp_2(10)
{
@Override
public Lamp_2 nextLamp()
{
return GREEN;
}
};
public static final Lamp_2 YELLOW = new Lamp_2(50)
{
@Override
public Lamp_2 nextLamp()
{
return RED;
}
};
public static final Lamp_2 GREEN = new Lamp_2(45)
{
@Override
public Lamp_2 nextLamp()
{
return YELLOW;
}
};
private int time;//时间
private Lamp_2(int time)
{
this.time=time;
};

public abstract Lamp_2 nextLamp();
@Override
public String toString()
{
return this==RED?"RED":this==YELLOW?"YELLOW":"GREEN";
}
}
}




将大量的if else语句转成了一个个独立的类


枚举类的基本应用:
在成员位置上可以定义枚举


枚举元素常用方法:
name();  获取元素名
ordinal();  获取元素的名次
getClass(); 获取元素的类名


枚举类的常用方法:
valueOf();//把字符变成实例对象
values(); 以数组形式返回枚举中所有的元素


带构造方法的枚举
1.枚举的构造方法只能用private修饰,
2.定义其他所有的信息,只能定义在元素后面


带构造方法以及抽象方法的枚举

package day1;
//带构造方法与带抽象方法的枚举类
//还有枚举的常用方法
public class EnumTest3
{
public static void main(String[] args)
{
Lamp lamp=Lamp.RED;
System.out.println(lamp.name());//获取名字
System.out.println(lamp.ordinal());//获取名次
System.out.println(lamp.getClass()); //获取类名
System.out.println(lamp.toString());//toString
System.out.println(lamp.nextLamp()); //下一灯

//枚举类方法
System.out.println(Lamp.valueOf("RED"));//根据元素名字获取元素
System.out.println(Lamp.values().length);//返回整个枚举中的所有元素

}
@SuppressWarnings("unused")
public enum Lamp
{
RED(10)
{
@Override
public Lamp nextLamp()
{
return GREEN;
}
},GREEN(40)
{
@Override
public Lamp nextLamp()
{
return YELLOW;
}
},YELLOW(5)
{
@Override
public Lamp nextLamp()
{
return RED;
}
};
private int time;
private Lamp(int time)
{
this.time=time;
}
//下一个灯
public abstract Lamp nextLamp();
}
}




枚举只有一个成员时,就可以当做一种单例的实现方式


反射:


Class类代表的是java中各个javA类的这一类事物
常用方法:
getInterfaces();//获取类实现的所有接口
getMethod();//获取单个方法
getMethods();//获取类的所有方法
getField();获取某一个字段
getFields(); 获取所以字段
getPackage();获取包名
getName();//获取类名


获取字节码对象有三种方法:
1.类名.class
2.对象.getClass();
3.Class.forName();指定包名


package day1;
//反射的入门
public class ReflectTest
{
@SuppressWarnings("rawtypes")
public static void main(String[] args)throws Exception
{
//三种方式获取字节码对象
ReflectTest reflectTest=new ReflectTest();
Class class1=reflectTest.getClass();
System.out.println(class1.getName());

Class class2=ReflectTest.class;
System.out.println(class2.getName());

Class class3=Class.forName("day1.ReflectTest");
System.out.println(class3.getName());

System.out.println(Integer.class == int.class);//false
System.out.println(Integer.TYPE == int.class);//true

System.out.println(int.class.isPrimitive());//true
System.out.println(int[].class.isArray());//ture

System.out.println(void.class.getName());
System.out.println(Void.class.getName());


}
}



九大预定义Class实例对象
八个基本类型加void


Reflect反射


isPrimitive();是否是基本类型
isArray();是否是数组


int.class==Integer.class; //false
int,class==Integer.TYPE;  //true


int[].class不是基本类型,是一个数组类型


总之,只要在源程序出现的类型都有各自class实例对象,例如int[],void,唯且只有一份


反射概念:
反射就是把java类中的各种成分映射成相应的java类


例如有一个Method对一个method类实例


构造方法的反射:
Constructor 
 

newInstance(); 利用反射实例化对象


package day1;

import java.lang.reflect.Constructor;

// 构造方法的反射
public class ConStructorReflect
{
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args)throws Exception
{
Class clazz=Test.class;

//获取指定参数的构造函数
Constructor constructor=clazz.getConstructor(int.class);
constructor.newInstance(10);

//获取所有的构造函数
Constructor[] constructors=clazz.getConstructors();
System.out.println(constructors.length);

for (Constructor constructor2 : constructors)
{
//遍历带参的
Class[] classes=constructor2.getParameterTypes();
for (Class class1 : classes)
{
System.out.println(class1.getName());
}
}
}
}



字段的反射:
Field


反射比较消耗时间,性能严重下降


alt+shift+s  //对方法实现


暴力反射
如果字段是private,用getDeclareField();可以查看,设置setAccessible(true);可以进行访问

package day1;

import java.lang.reflect.Field;

//成员变量反射
public class FieldReflect
{
public static void main(String[] args)throws Exception
{

Test test=new Test();
test.setName("坑爹");
Class<? extends Test> clazz=test.getClass();
//Class<? super Test> clazz=test.getClass();
//获取私有的
Field fieldName=clazz.getDeclaredField("name");
//暴力反射
fieldName.setAccessible(true);
System.out.println(fieldName.get(test));

//获取非私有de
Field s1Field=clazz.getField("s1");
System.out.println(s1Field.get(test));
}
}



作业:
将任意一个对象中的所有String类型成员变量所在对应的字符串内容'b'改成'a'




getType(); 获取字段的类型


比较字节码对象用== 


package day1;

import java.lang.reflect.Field;

//将Test 类public的 String值含b 改成a
public class ReflectPractice1
{
public static void main(String[] args)throws Exception
{
Test test=new Test();
Field[] fields=test.getClass().getFields();

for (Field field : fields)
{
if(field.getType().equals(String.class))
{
String oldVal=(String)field.get(test);
String newVal=oldVal.replace('b', 'a');
field.set(test, newVal);
System.out.println(field.get(test));
}
}
}
}



Method类的反射
代表类中的一个成员方法


当对象传参为null,这个方法为静态方法
JDK1.4没有可变参数,使用的是new Object[]{数据}

package day1;

import java.lang.reflect.Method;

//方法反射
public class MethodReflect
{
@SuppressWarnings("unchecked")
public static void main(String[] args)throws Exception
{
Test test=new Test();

@SuppressWarnings("rawtypes")
Class clazz=test.getClass();

//执行非静态方法
Method method=clazz.getMethod("method", null);

method.invoke(test, null);


//执行静态方法

Method staticmMethod=clazz.getMethod("staticMethod", int[].class);
staticmMethod.invoke(null, new int[]{1,2,3});
}
}



用反射执行某个类的main方法


为什么要用反射? 当写程序不明确要执行那个类的时

数组传参的两个方案:
1.new Object[]{new String[]{}}
2.(Object)new String[]{}  编译时不要把object当数组来拆


package day1;

import java.lang.reflect.Method;

public class MainReflect
{
public static void main(String[] args)throws Exception
{
Method mainMethod=Test.class.getMethod("main", String[].class);

//mainMethod.invoke(null, new String[]{"异常","游戏"}); //错误的

//以下两种方式可行
mainMethod.invoke(null, (Object)new String[]{"异常","游戏"});
mainMethod.invoke(null, new Object[]{ new String[]{"异常","游戏"}});
}
}



数组的反射


1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的class实例对象
2.代表数组的class实例对象的getSuperClass方法返回的是父类的Object对应的class
3.基本类型的一维数组可以当做Object类型使用,不能当Object[]类型使用,引用类型的一维数组
可以当做Object对象,也可以当做Object[]类型使用.


package day1;
//数组的反射
public class ArrayReflect
{
@SuppressWarnings("unused")
public static void main(String[] args)
{
int[] a1=new int[3];
int[] a2=new int[4];
int[][] a3=new int[3][4];
String[] a4=new String[3];

Object obj1=a1;
Object obj2=a2;
Object obj3=a3;
Object obj6=a4;

//Object[] obj4=a1; //编译错误 基本类型一维数组不能当object[]对象
Object[] obj5=a3;
Object[] obj7=a4;


System.out.println(a1.getClass() == a2.getClass());//true
//System.out.println(a1.getClass() == a3.getClass());//编译出错
//System.out.println(a1.getClass() == a4.getClass());//编译出错
//System.out.println(a1.getClass() == Integer.class);;//编译出错


System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a3.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
}
}



Arrays.asList(); JDK1.4与1.5的区别
当传入基本数据类数组的时候,会把基本类型数组当做集合一个元素,当传入的引用类型数组的时候,会把引用数组元素当做集合的元素


对数组进行反射.定义一个方法可以打印数组和单个对象

package day1;

import java.lang.reflect.Array;

//对数组反射 一个方法可以打印数组与非数组 用到Array
public class ArrayReflectPrint
{
public static void main(String[] args)
{
int[] arr={1,3,14};
String string="nimei";
print(arr);
print(string);
}
public static void print(Object obj)
{
if(obj.getClass().isArray())
{
int len = Array.getLength(obj);
System.out.println(len);

for (int i = 0; i < len; i++)
{
System.out.println(Array.get(obj, i));
}

}else {
System.out.println(obj);
}
}
}



没有办法得到数组的类型,能获取某一个具体元素类型



要记得,面向父类或面向接口编程


ArrayList 与HashSet


HashCode方法的作用: 为保证对象的唯一,提高查找性能,


当一个对象中被存进HashSet集合,那么参与哈希值运算的字段不能被修改,否则过多会导致内存泄露


package day1;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

//hashcode方法
public class ArrayListAndHashSet
{
public static void main(String[] args)
{
Person p1=new Person("武松",10);
Person p2=new Person("孤独",32);
Person p3=new Person("老虎",23);
Person p4=new Person("老虎",23);

//ArrayList
ArrayList<Person> al=new ArrayList<Person>();
al.add(p1);
al.add(p2);
al.add(p3);
al.add(p4);
al.add(p1);

System.out.println(al);



//HashSet
Set<Person> set=new HashSet<Person>();
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
set.add(p1);

p1.setAge(20); //修改了参与了哈希值运算的成员变量, 将不能成功删除元素
set.remove(p1);

System.out.println(set);
}
}



反射的作用;
实现框架功能


框架:人家调用你
工具:你调用人家

因为在写程序时,无法明确要调用的类型,所以在程序无法new某个类的实例对象时,而是用反射来做

package day1;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;

//不确定要创建那个实例对象 读取配置文件来创建
public class UnknowReflect
{
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args)throws Exception
{
//当在包名.resource目录下时

// 相对路径 不用完整包名 如果不是包名.目录下 这样要加前面要加/
InputStream inStream=UnknowReflect.class.getResourceAsStream("resource/config.properties");


//这个要是绝对路径
//InputStream inStream=new FileInputStream("E:/android/projects/javaenhance1/src/day1/resource/config.properties");


//要完整包名 相对路径
//InputStream inStream=UnknowReflect.class.getClassLoader().getResourceAsStream("day1/resource/config.properties");

Properties properties=new Properties();
properties.load(inStream);

String className=properties.getProperty("className");

Person p1=new Person("武松",10);
Person p2=new Person("孤独",32);
Person p3=new Person("老虎",23);

Class clazz=Class.forName(className);

//ArrayList
ArrayList<Person> al=(ArrayList<Person>) clazz.newInstance();
al.add(p1);
al.add(p2);
al.add(p3);

System.out.println(al);
}
}



配置文件到底放在那里?


web有个方法getRealPath();;获取项目的硬盘位置


一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的


用InputStream对配置文件可读可写


这个只能读
类.class.getClassLoader().getResourceAsStream(); //要指定包名


类.class.getResourceAsStream(); //不用指定包名


框架内部就是使用类加载器加载配置文件

 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————