- 浏览: 260036 次
- 性别:
- 来自: 北京
-
博客专栏
-
-
Java并发包源码解析
浏览量:103860
最新评论
-
746238836:
整个RingBuffer内部做了大量的缓存行填充,前后各填充了 ...
disruptor-3.3.2源码解析(2)-队列 -
xiangshouxiyang:
群加不了。。。
Jdk1.7 ForkJoin框架源码解析汇总 -
有贝无患:
acquire方法里面为什么tryAcquire会被调用多次 ...
Jdk1.6 JUC源码解析(6)-locks-AbstractQueuedSynchronizer -
zwy_qz:
library_call.cpp 里面的内联操作 inline ...
Jdk1.6 JUC源码解析(1)-atomic-AtomicXXX -
sunwang810812:
您好,正在学习您的文章,中间有一段,一直没明白:“privat ...
Jdk1.6 JUC源码解析(6)-locks-AbstractQueuedSynchronizer
看这个类之前,先看一下Java的枚举——Enum。
枚举是啥?编码时我们经常需要写int型常量,在某些情况下(不是全部),用枚举更合适。举个例子,在程序中需要两个常量表示性别(男、女)。可能刚开始(JDK1.5之前)我们会这样写:
当然这么写也没什么错误,还算一目了然,用起来也还算方便。但仔细想一下这样会有什么问题!首先,假如我们有一个方法需要传一个表示男女的参数,方法内部根据参数做一些逻辑。如下:
这个方法的意图是根据性别做一些事情。但一个巨大的问题就是参数类型!应该传一个表示性别的类型,这里却是int类型。这种情况下,就算你把参数名称描述的很清晰,把方法注释写的巨牛逼,但用你方法的人照样可以无视一切,给你传个2!这下你2了,方法里面加判断吧。抛个运行时异常,说你的方法暂不支持人妖等其他性别。。。这个问题的根源所在就是int型的常量类型不安全的。
当然你还可能希望你的MALE常量可以打印,print(MALE)一下,输出的是"MALE"而不是一个"1"(尽管这个表示男性也很形象
)。
怎么来解决以上的问题呢,也许你又在想,Java是面向对象的吗,搞个对象不就行了。定义一个类型来表示性别,只提供两种实例表示男女,这个类还不能被扩展等等。如下:
这么写已经基本可以解决类型安全,输出有意义的问题了。但是还有几个小问题。首先,如果我们只写一个简单的常量的话,这样写代码有点多(和枚举比较),当然如果你有时间的话,这都不是问题;其次,如果要遍历这类常量的话(看看Sex里有几种性别),还需要添加额外的外码;最后,其实类型安全问题还是没有完全解决,调用者照样可以利用反射创建一个"人妖"实例。
其实枚举(Enum)做的也是上面的工作,它还做了更多的工作,从很基础的层面提供了支持。我们用枚举写一下上面的例子:
是不是比上面的例子代码少一点点,也直观一些。当然这里仅仅因为要打印的内容正好是常量的字面量(如:MALE),如果要打印"男性"的话,就得在加一个name属性了。而且我们一眼看上去,它是一个Enum类型,也就知道这个类的意图了。
JDK中和枚举对应的类是java.lang.Enum。来看一下源代码。
枚举的内部有2个属性。一个是name,表示枚举具体实例的名称。另一个是ordinal表示枚举实例的序数(枚举实例在定义时出现的顺序,从0开始)。从ordinal的注释也能看到,这个属性一般不会被外部程序用到,只有一些基于枚举的数据结构(如EnumSet和EnumMap这两货)中会用到。
枚举内容简单总结到这儿,下面看一下java.util.EnumMap吧。直接看源码:
和其他的Map实现一样,也扩展自AbstractMap,可序列化可克隆。注意Key的类型声明,必须是Enum的子类。继续往下看。
keyType保存Key的类型;keyUniverse保存Key,vals保存对应的Value。通过注释可以知道Key和Value是通过下标来映射的,不同于其他Map实现,这里没有散列表等等复杂的数据结构,只有两个数组,通过下标对应。这样的实现无疑是高效快速的。
构造方法中会通过keyType调用一个getKeyUniverse方法来获取所有的枚举实例,并放到keyUniverse中缓存起来。
下面看一个关键的方法——put方法。
可以看到,用来映射Key和Value的下标就是Enum的ordinal。这样做即可以保证映射的正确性,又能保证遍历顺序和Enum定义的顺序一致。
其他方法大概看一下,没有复杂的数据结构,都很容易看懂。
总之,当我们要使用以枚举为Key的Map时,使用这个再合适不过了。当然也可以使用其他实现如HashMap等,但无疑在这种场景下,EnumMap更加高效。
枚举是啥?编码时我们经常需要写int型常量,在某些情况下(不是全部),用枚举更合适。举个例子,在程序中需要两个常量表示性别(男、女)。可能刚开始(JDK1.5之前)我们会这样写:
/** * 男 */ public static final int MALE = 1; /** * 女 */ public static final int FEMALE = 0;
当然这么写也没什么错误,还算一目了然,用起来也还算方便。但仔细想一下这样会有什么问题!首先,假如我们有一个方法需要传一个表示男女的参数,方法内部根据参数做一些逻辑。如下:
public void doSthBySex(int sex){ //... }
这个方法的意图是根据性别做一些事情。但一个巨大的问题就是参数类型!应该传一个表示性别的类型,这里却是int类型。这种情况下,就算你把参数名称描述的很清晰,把方法注释写的巨牛逼,但用你方法的人照样可以无视一切,给你传个2!这下你2了,方法里面加判断吧。抛个运行时异常,说你的方法暂不支持人妖等其他性别。。。这个问题的根源所在就是int型的常量类型不安全的。
当然你还可能希望你的MALE常量可以打印,print(MALE)一下,输出的是"MALE"而不是一个"1"(尽管这个表示男性也很形象

怎么来解决以上的问题呢,也许你又在想,Java是面向对象的吗,搞个对象不就行了。定义一个类型来表示性别,只提供两种实例表示男女,这个类还不能被扩展等等。如下:
public final class Sex { private int type; private String name; private Sex(int type,String name) { this.type = type; this.name = name; } /** * 男性 */ public static final Sex MALE = new Sex(1, "MALE"); /** * 女性 */ public static final Sex FEMALE = new Sex(0, "FEMALE"); public int getType() { return type; } public String getName() { return name; } public String toString(){ return name; } }
这么写已经基本可以解决类型安全,输出有意义的问题了。但是还有几个小问题。首先,如果我们只写一个简单的常量的话,这样写代码有点多(和枚举比较),当然如果你有时间的话,这都不是问题;其次,如果要遍历这类常量的话(看看Sex里有几种性别),还需要添加额外的外码;最后,其实类型安全问题还是没有完全解决,调用者照样可以利用反射创建一个"人妖"实例。
其实枚举(Enum)做的也是上面的工作,它还做了更多的工作,从很基础的层面提供了支持。我们用枚举写一下上面的例子:
public enum Sex { /** * 女性 */ FEMALE(0), /** * 男性 */ MALE(1); private int type; private Sex(int type) { this.type = type; } public int getType() { return type; } }
是不是比上面的例子代码少一点点,也直观一些。当然这里仅仅因为要打印的内容正好是常量的字面量(如:MALE),如果要打印"男性"的话,就得在加一个name属性了。而且我们一眼看上去,它是一个Enum类型,也就知道这个类的意图了。
JDK中和枚举对应的类是java.lang.Enum。来看一下源代码。
/** * This is the common base class of all Java language enumeration types. * * @author Josh Bloch * @author Neal Gafter * @version %I%, %G% * @since 1.5 */ public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { /** * The name of this enum constant, as declared in the enum declaration. * Most programmers should use the {@link #toString} method rather than * accessing this field. */ private final String name; /** * Returns the name of this enum constant, exactly as declared in its * enum declaration. * * <b>Most programmers should use the {@link #toString} method in * preference to this one, as the toString method may return * a more user-friendly name.</b> This method is designed primarily for * use in specialized situations where correctness depends on getting the * exact name, which will not vary from release to release. * * @return the name of this enum constant */ public final String name() { return name; } /** * The ordinal of this enumeration constant (its position * in the enum declaration, where the initial constant is assigned * an ordinal of zero). * * Most programmers will have no use for this field. It is designed * for use by sophisticated enum-based data structures, such as * {@link java.util.EnumSet} and {@link java.util.EnumMap}. */ private final int ordinal; /** * Returns the ordinal of this enumeration constant (its position * in its enum declaration, where the initial constant is assigned * an ordinal of zero). * * Most programmers will have no use for this method. It is * designed for use by sophisticated enum-based data structures, such * as {@link java.util.EnumSet} and {@link java.util.EnumMap}. * * @return the ordinal of this enumeration constant */ public final int ordinal() { return ordinal; } /** * Sole constructor. Programmers cannot invoke this constructor. * It is for use by code emitted by the compiler in response to * enum type declarations. * * @param name - The name of this enum constant, which is the identifier * used to declare it. * @param ordinal - The ordinal of this enumeration constant (its position * in the enum declaration, where the initial constant is assigned * an ordinal of zero). */ protected Enum(String name, int ordinal) { this.name = name; this.ordinal = ordinal; } /** * Returns the name of this enum constant, as contained in the * declaration. This method may be overridden, though it typically * isn't necessary or desirable. An enum type should override this * method when a more "programmer-friendly" string form exists. * * @return the name of this enum constant */ public String toString() { return name; } /** * Returns true if the specified object is equal to this * enum constant. * * @param other the object to be compared for equality with this object. * @return true if the specified object is equal to this * enum constant. */ public final boolean equals(Object other) { return this==other; } /** * Returns a hash code for this enum constant. * * @return a hash code for this enum constant. */ public final int hashCode() { return super.hashCode(); } /** * Throws CloneNotSupportedException. This guarantees that enums * are never cloned, which is necessary to preserve their "singleton" * status. * * @return (never returns) */ protected final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } /** * Compares this enum with the specified object for order. Returns a * negative integer, zero, or a positive integer as this object is less * than, equal to, or greater than the specified object. * * Enum constants are only comparable to other enum constants of the * same enum type. The natural order implemented by this * method is the order in which the constants are declared. */ public final int compareTo(E o) { Enum other = (Enum)o; Enum self = this; if (self.getClass() != other.getClass() && // optimization self.getDeclaringClass() != other.getDeclaringClass()) throw new ClassCastException(); return self.ordinal - other.ordinal; } /** * Returns the Class object corresponding to this enum constant's * enum type. Two enum constants e1 and e2 are of the * same enum type if and only if * e1.getDeclaringClass() == e2.getDeclaringClass(). * (The value returned by this method may differ from the one returned * by the {@link Object#getClass} method for enum constants with * constant-specific class bodies.) * * @return the Class object corresponding to this enum constant's * enum type */ public final Class<E> getDeclaringClass() { Class clazz = getClass(); Class zuper = clazz.getSuperclass(); return (zuper == Enum.class) ? clazz : zuper; } /** * Returns the enum constant of the specified enum type with the * specified name. The name must match exactly an identifier used * to declare an enum constant in this type. (Extraneous whitespace * characters are not permitted.) * * @param enumType the <tt>Class</tt> object of the enum type from which * to return a constant * @param name the name of the constant to return * @return the enum constant of the specified enum type with the * specified name * @throws IllegalArgumentException if the specified enum type has * no constant with the specified name, or the specified * class object does not represent an enum type * @throws NullPointerException if <tt>enumType</tt> or <tt>name</tt> * is null * @since 1.5 */ public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { T result = enumType.enumConstantDirectory().get(name); if (result != null) return result; if (name == null) throw new NullPointerException("Name is null"); throw new IllegalArgumentException( "No enum const " + enumType +"." + name); } /** * prevent default deserialization */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("can't deserialize enum"); } private void readObjectNoData() throws ObjectStreamException { throw new InvalidObjectException("can't deserialize enum"); } /** * enum classes cannot have finalize methods. */ protected final void finalize() { } }
枚举的内部有2个属性。一个是name,表示枚举具体实例的名称。另一个是ordinal表示枚举实例的序数(枚举实例在定义时出现的顺序,从0开始)。从ordinal的注释也能看到,这个属性一般不会被外部程序用到,只有一些基于枚举的数据结构(如EnumSet和EnumMap这两货)中会用到。
枚举内容简单总结到这儿,下面看一下java.util.EnumMap吧。直接看源码:
public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements java.io.Serializable, Cloneable {
和其他的Map实现一样,也扩展自AbstractMap,可序列化可克隆。注意Key的类型声明,必须是Enum的子类。继续往下看。
/** * The <tt>Class</tt> object for the enum type of all the keys of this map. * * @serial */ private final Class<K> keyType; /** * All of the values comprising K. (Cached for performance.) */ private transient K[] keyUniverse; /** * Array representation of this map. The ith element is the value * to which universe[i] is currently mapped, or null if it isn't * mapped to anything, or NULL if it's mapped to null. */ private transient Object[] vals; /** * The number of mappings in this map. */ private transient int size = 0;
keyType保存Key的类型;keyUniverse保存Key,vals保存对应的Value。通过注释可以知道Key和Value是通过下标来映射的,不同于其他Map实现,这里没有散列表等等复杂的数据结构,只有两个数组,通过下标对应。这样的实现无疑是高效快速的。
/** * Creates an empty enum map with the specified key type. * * @param keyType the class object of the key type for this enum map * @throws NullPointerException if <tt>keyType</tt> is null */ public EnumMap(Class<K> keyType) { this.keyType = keyType; keyUniverse = getKeyUniverse(keyType); vals = new Object[keyUniverse.length]; } /** * Creates an enum map with the same key type as the specified enum * map, initially containing the same mappings (if any). * * @param m the enum map from which to initialize this enum map * @throws NullPointerException if <tt>m</tt> is null */ public EnumMap(EnumMap<K, ? extends V> m) { keyType = m.keyType; keyUniverse = m.keyUniverse; vals = (Object[]) m.vals.clone(); size = m.size; } /** * Creates an enum map initialized from the specified map. If the * specified map is an <tt>EnumMap</tt> instance, this constructor behaves * identically to {@link #EnumMap(EnumMap)}. Otherwise, the specified map * must contain at least one mapping (in order to determine the new * enum map's key type). * * @param m the map from which to initialize this enum map * @throws IllegalArgumentException if <tt>m</tt> is not an * <tt>EnumMap</tt> instance and contains no mappings * @throws NullPointerException if <tt>m</tt> is null */ public EnumMap(Map<K, ? extends V> m) { if (m instanceof EnumMap) { EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m; keyType = em.keyType; keyUniverse = em.keyUniverse; vals = (Object[]) em.vals.clone(); size = em.size; } else { if (m.isEmpty()) throw new IllegalArgumentException("Specified map is empty"); keyType = m.keySet().iterator().next().getDeclaringClass(); keyUniverse = getKeyUniverse(keyType); vals = new Object[keyUniverse.length]; putAll(m); } } /** * Returns all of the values comprising K. * The result is uncloned, cached, and shared by all callers. */ private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) { return SharedSecrets.getJavaLangAccess() .getEnumConstantsShared(keyType); }
构造方法中会通过keyType调用一个getKeyUniverse方法来获取所有的枚举实例,并放到keyUniverse中缓存起来。
下面看一个关键的方法——put方法。
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for this key, the old * value is replaced. * * @param key the key with which the specified value is to be associated * @param value the value to be associated with the specified key * * @return the previous value associated with specified key, or * <tt>null</tt> if there was no mapping for key. (A <tt>null</tt> * return can also indicate that the map previously associated * <tt>null</tt> with the specified key.) * @throws NullPointerException if the specified key is null */ public V put(K key, V value) { typeCheck(key); int index = ((Enum)key).ordinal(); Object oldValue = vals[index]; vals[index] = maskNull(value); if (oldValue == null) size++; return unmaskNull(oldValue); }
可以看到,用来映射Key和Value的下标就是Enum的ordinal。这样做即可以保证映射的正确性,又能保证遍历顺序和Enum定义的顺序一致。
其他方法大概看一下,没有复杂的数据结构,都很容易看懂。
/** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * <p>More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code (key == k)}, * then this method returns {@code v}; otherwise it returns * {@code null}. (There can be at most one such mapping.) * * <p>A return value of {@code null} does not <i>necessarily</i> * indicate that the map contains no mapping for the key; it's also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey containsKey} operation may be used to * distinguish these two cases. */ public V get(Object key) { return (isValidKey(key) ? unmaskNull(vals[((Enum)key).ordinal()]) : null); } /** * Removes the mapping for this key from this map if present. * * @param key the key whose mapping is to be removed from the map * @return the previous value associated with specified key, or * <tt>null</tt> if there was no entry for key. (A <tt>null</tt> * return can also indicate that the map previously associated * <tt>null</tt> with the specified key.) */ public V remove(Object key) { if (!isValidKey(key)) return null; int index = ((Enum)key).ordinal(); Object oldValue = vals[index]; vals[index] = null; if (oldValue != null) size--; return unmaskNull(oldValue); }
总之,当我们要使用以枚举为Key的Map时,使用这个再合适不过了。当然也可以使用其他实现如HashMap等,但无疑在这种场景下,EnumMap更加高效。
发表评论
-
Jdk1.6 Collections Framework源码解析(12)-TreeMap、TreeSet
2016-01-03 16:06 2216Jdk1.6 Collections Framework ... -
Jdk1.6 Collections Framework源码解析(11)-EnumSet
2015-12-29 18:25 1920Jdk1.6 Collections Framework源 ... -
Jdk1.6 JUC源码解析(26)-ConcurrentSkipListMap、ConcurrentSkipListSet
2015-11-03 03:08 5481Jdk1.6 JUC源码解析(26)-Concurrent ... -
Jdk1.6 JUC源码解析(25)-ConcurrentHashMap
2015-10-30 19:02 2610Jdk1.6 JUC源码解析(25)-Co ... -
Jdk1.6 集合框架源码解析汇总
2015-10-29 22:05 3528Jdk1.6 集合框架源码解析汇总 非并发: ... -
Jdk1.6 JUC源码解析(24)-ConcurrentLinkedQueue
2015-10-29 19:02 1992Jdk1.6 JUC源码解析(24)-ConcurrentL ... -
Jdk1.6 JUC源码解析(23)-CopyOnWriteArrayList、CopyOnWriteArraySet
2015-10-29 18:55 1905Jdk1.6 JUC源码解析(23)-Cop ... -
Jdk1.6 JUC源码解析(22)-LinkedBlockingDeque
2015-10-29 18:47 1703Jdk1.6 JUC源码解析(22)-LinkedBloc ... -
Jdk1.6 JUC源码解析(18)-DelayQueue
2015-10-27 19:25 2465Jdk1.6 JUC源码解析(18)-DelayQueue ... -
Jdk1.6 JUC源码解析(15)-SynchronousQueue
2015-10-26 19:19 2634Jdk1.6 JUC源码解析(15)-Synchronou ... -
Jdk1.6 JUC源码解析(14)-PriorityBlockingQueue
2015-10-25 03:22 2371Jdk1.6 JUC源码解析(14)-Pr ... -
Jdk1.6 JUC源码解析(13)-LinkedBlockingQueue
2015-10-24 22:28 1888Jdk1.6 JUC源码解析(13)-LinkedBloc ... -
Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue
2015-10-23 20:03 2243Jdk1.6 JUC源码解析(12)-Ar ... -
Jdk1.6 Collections Framework源码解析(9)-PriorityQueue
2013-09-03 20:37 2120开发中有时会遇到这样的情况。要求某个调度器去调 ... -
Jdk1.6 Collections Framework源码解析(8)-WeakHashMap
2013-09-02 11:43 2229总结这个类之前,首先看一下Java引用的相关知 ... -
Jdk1.6 Collections Framework源码解析(7)-HashSet、LinkedHashSet
2013-08-28 11:34 1709本篇总结一 ... -
Jdk1.6 Collections Framework源码解析(6)-IdentityHashMap
2013-08-27 14:10 1639这篇总结一下java.util.Identit ... -
Jdk1.6 Collections Framework源码解析(5)-LinkedHashMap
2013-08-20 14:28 1829前面总结了java.util.HashMap, ... -
Jdk1.6 Collections Framework源码解析(4)-HashMap
2013-08-19 13:59 2057开发中常常 ... -
Jdk1.6 Collections Framework源码解析(3)-ArrayDeque
2013-08-12 10:59 3736表、栈和队列是三种基本的数据结构,前面总结的A ...
相关推荐
对集合框架进行了优化,如`ListIterator`的增强,`Collections.sort()`支持自定义比较器,以及`EnumSet`和`EnumMap`的引入,专门用于枚举类型的高效操作。 9. **枚举的常量工厂方法(Enum Constant Factory ...
- **扩容策略**:在JDK 6中是1.5倍,而在JDK 7及以后版本中则是1.5倍或2倍(取决于实际情况) - **特点**: - 底层使用数组实现,支持随机访问,适用于大量查找操作。 - 不适合频繁的插入和删除操作,因为这会...
物联网设备开发_蓝牙低能耗BLE技术_小米手环1非心率版数据读取与控制_实现Android平台下小米手环1代非心率版设备的蓝牙连接_步数数据获取_电量监测_震动控制功能_适用于An
内容概要:本文详细探讨了基于定子磁链定向矢量控制的双馈感应发电机(DFIG)空载并网模型。首先介绍了传统的PI控制方法,指出其在动态响应方面的局限性。接着,提出了通过引入模糊控制来改进PI控制的方法,展示了模糊控制在提高动态响应速度和减少误差方面的显著优势。文中提供了详细的代码实现和实验结果对比,证明了改进模型的有效性和优越性。 适合人群:从事电力电子、风电控制系统设计的研究人员和技术人员,尤其是对双馈感应发电机并网控制感兴趣的读者。 使用场景及目标:适用于希望深入了解DFIG并网控制策略的技术人员,旨在帮助他们掌握如何通过模糊控制优化PI控制器,以提高系统的动态响应速度和稳定性,减少并网瞬间的电流冲击。 其他说明:文章不仅提供了理论分析,还包括具体的代码实现和实验数据,便于读者理解和复现。同时,强调了模糊控制并非万能解决方案,需要结合实际情况进行调整和优化。
MuGuiLin_VoiceDictation_17128_1745869163155
termux,在安卓平台的模拟终端
内容概要:本文详细介绍了基于混合遗传算法-蚁群算法优化随机森林回归预测(GA-ACO-RFR)的MATLAB实现方法及其在电力领域的应用。首先,文章讲解了如何读取和预处理电厂运行数据,将其转化为可用于建模的数值矩阵。接着,深入探讨了GA-ACO-RFR的工作原理,包括遗传算法的全局搜索能力以及蚁群算法的局部寻优特性,并展示了具体的优化过程和关键代码。随后,文章演示了如何利用优化后的参数构建最终的随机森林回归模型,并进行了预测和评估,证明了该方法能够显著提高电厂运行数据的预测精度。此外,文中还提供了多个实用技巧,如数据归一化、种群初始化、适应度函数设计等。 适合人群:对电力数据分析感兴趣的工程师和技术人员,尤其是那些希望通过MATLAB实现复杂算法优化的人士。 使用场景及目标:适用于需要精确预测电厂运行参数(如主汽温度、发电负荷等)的场合,旨在帮助用户掌握GA-ACO-RFR的具体实现步骤,从而应用于实际项目中,达到优化电厂管理和提高能源效率的目的。 其他说明:文章不仅提供了详细的理论解释,还包括了大量的代码实例和配图,使得读者更容易理解和实践。同时,作者还分享了一些个人经验,如参数设置建议和性能优化技巧,进一步增强了文章的实用性。
内容概要:本文详细介绍了利用滑模观测器(SMO)实现永磁同步电机(PMSM)无位置传感器控制的方法及其仿真模型构建。首先解释了滑模观测器的工作原理,即通过构造滑动模态面使系统状态沿预设轨迹运动,从而估算电机的位置和转速。文中展示了具体的MATLAB/Simulink代码实现,包括滑模观测器的核心算法、锁相环(PLL)用于位置提取以及低通滤波器的应用。此外,讨论了调试过程中遇到的问题及解决方案,如滑模增益的选择、电流观测误差的处理、低速运行时的稳定性提升等。最后,通过仿真结果验证了该方案的有效性和鲁棒性。 适合人群:从事电机控制系统研究与开发的技术人员,尤其是对无位置传感器控制技术和滑模观测器感兴趣的工程师。 使用场景及目标:适用于希望减少硬件成本和复杂度,提高系统可靠性的情况。主要目标是在不使用物理位置传感器的情况下,实现对永磁同步电机的精确控制,确保系统的稳定性和响应速度。 其他说明:文中提供了丰富的代码片段和调试技巧,有助于读者快速理解和应用滑模观测器技术。同时强调了仿真与实际应用之间的差异,提醒开发者在实际部署时需要注意的问题。
知识领域_社区论坛系统_微信小程序_Java后端开发_网络安全_性能优化_技术关键词_uni-app_Vue2_SpringBoot_MybatisPlus_Redis_Mysql
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
DAB转换器 双有源桥(DAB)转换器是一种高频隔离DC-DC转换器,广泛应用于电动汽车充电器、可再生能源系统。 1输入侧 使用直流电压源 使用IGBT或MOSFET连接到全桥逆变器(通用桥) 使用移相PWM发生器进行控制 2.变压器 使用理想变压器或物理变压器模型 确保隔离并设置匝数比(例如1:1,或用于升压/降压) 3.输出侧 使用另一个全桥逆变器(充当整流器) 连接直流滤波电容器和负载(或电池) 4.控制策略 实施移相控制器: 相对于输入移位输出桥门信号
内容概要:本文详细介绍了车载充电机的完整设计方案,重点探讨了LLC谐振变换器和PFC(功率因数校正)的技术细节。文中不仅提供了LLC和PFC的C语言源码示例,还深入讲解了原理图、PCB布局及变压器设计等方面的内容。LLC部分强调了谐振频率的计算及其对变换器稳定性的影响,而PFC部分则关注于功率因数的提升方法。此外,文章还分享了许多实用的设计经验和调试技巧,如PCB布局的注意事项、变压器参数的选择等。 适合人群:从事车载充电技术研发的工程师和技术爱好者,尤其是希望深入了解LLC和PFC技术原理的人群。 使用场景及目标:帮助工程师优化车载充电机的设计,提高产品的性能和可靠性,同时为初学者提供全面的学习资料,加速技术掌握。 其他说明:文中提供的方案不仅适用于车载充电机,还可以应用于其他类似设备的研发,如吸尘器电源等。通过实际案例和详细的调试指南,使读者能够更好地理解和应用相关技术。
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了基于西门子PLC(如S7-1200和S7-200)和组态王6.55构建的锅炉控制系统。主要内容涵盖梯形图程序设计、硬件接线图、IO分配以及组态画面的设计。文章首先解释了锅炉控制的基本原理,包括手动模式和自动PID调节的梯形图逻辑,接着讨论了温度、压力等重要参数的采集与处理方法。此外,还探讨了组态王画面设计技巧,如动态属性绑定、动画效果实现等。最后分享了一些调试经验和优化建议,强调了安全冗余设计的重要性。 适合人群:从事工业自动化领域的工程师和技术人员,特别是熟悉PLC编程和HMI开发的专业人士。 使用场景及目标:适用于新建或改造锅炉控制系统项目,旨在帮助技术人员掌握完整的系统设计方案,确保系统稳定可靠运行,减少故障发生率,降低维护成本。 其他说明:文中提供了大量实际案例和经验总结,对于理解和应用工业自动化技术具有很高的参考价值。
scratch少儿编程逻辑思维游戏源码-海底冒险.zip
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了基于S7-1500 PLC和TP1500触摸屏的PID温度压力调节系统的应用案例。首先解释了PID控制的基础概念及其在S7-1500中的具体实现方法,包括使用FB41功能块进行温度调节的具体参数设置。接着探讨了S7-1500 PLC间的通讯机制,展示了如何利用STL语言编写通讯程序段,确保不同PLC之间的高效数据交换。此外,还讨论了TP1500触摸屏与PLC的交互方式,如变量关联和监控画面的设计,使得操作员能够便捷地监控和调整系统参数。文中提供了丰富的代码实例和技术细节,有助于深入理解S7-1500的强大功能及其在工业自动化领域的应用。 适合人群:从事工业自动化控制的技术人员,尤其是熟悉西门子PLC编程并希望深入了解S7-1500系列产品的工程师。 使用场景及目标:适用于需要构建稳定可靠的温度压力调节系统的工业环境,如钢铁厂、化工厂等。通过学习本文,读者可以掌握PID控制的基本原理、PLC编程技巧以及触摸屏与PLC的交互设计,从而提高项目的实施效率和质量。 其他说明:文中提到的一些关键技术和编程技巧对于解决实际工程中的难题非常有价值,例如PID参数整定、硬件联调等问题。同时,提供的代码示例可以直接应用于类似场景,减少了重复开发的工作量。
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;